diff --git a/README.md b/README.md index 8c188ff355b31ec3a713a3c2c1c1d6f7753f3336..6a5d1c3bd3604103eeb4ab33b812880fe415a2e0 100644 --- a/README.md +++ b/README.md @@ -15,133 +15,6 @@ For issue/bug-tracking, I recommend [git-bug](https://github.com/git-bug/git-bug). Currently all HTML is allowed in markdown, µgit is intended to be run by/for a trusted user. -## Features - -### Push-to-create - -Pushing to a repo path that doesn't exist yet creates it automatically, there's no separate "create repo" step. -Combined with [push options](#push-options), this means a repo can be created and configured in the same command as its first push: - -```sh -git push -o "private=false" ssh://git@example.com:8448/new-repo.git main -``` - -### Push options - -A handful of `git push -o =` (`--push-option`) options are read on every push to update the repo's metadata, in addition to actually pushing the ref(s): - -| Option | Value | Effect | -|----------------------|-------------------------------------------------------------|---------------------------------------------------------------------| -| `desc`/`description` | any string | Sets the repo description | -| `private` | `true`/`false` | Sets the repo's `private` tag (see [Configuration](#configuration)) | -| `tags` | comma-separated list, prefix an entry with `-` to remove it | Adds/removes tags on the repo, for filtering | - -For example: - -```sh -git push -o desc="My project" -o "private=false" -o "tags=go,-wip" origin main -``` - -Push options can be repeated (`-o key=value -o key2=value2`) and are applied in order; unrecognized options are ignored. - -### Search - -The web UI's repo search is a lightweight, `git grep`-style regex scan over the files at the tip of the default branch, implemented in-process rather than shelling out to `git`. -If you need more advanced code search, consider running something like [zoekt](https://github.com/sourcegraph/zoekt) alongside µgit rather than relying on the built-in search. - -## Installation - -### NixOS - -µgit ships a `flake.nix` with a NixOS module that can run one or more independent instances via `services.ugit.`. -Each instance gets its own user/group, home directory, and systemd service. -See `nix/module.nix` for the full list of options. - -```nix -{ - inputs.ugit.url = "git+https://git.jolheiser.com/ugit"; - - outputs = { self, nixpkgs, ugit, ... }: { - nixosConfigurations.example = nixpkgs.lib.nixosSystem { - modules = [ - ugit.nixosModules.default - { - services.ugit.public = { - enable = true; - authorizedKeysFile = "/etc/ugit/authorized_keys"; - config = { - show-private = false; - http.port = 8449; - }; - }; - } - ]; - }; - }; -} -``` - -The `config` option is written out as the instance's YAML config file (see [Configuration](#configuration) below), so any flag documented there can be set through it. - -### Everything else - -µgit is a single statically-linked Go binary with no runtime dependencies beyond `git` itself on `$PATH`. - -Build it from source with a recent Go toolchain: `go build ./cmd/ugitd`, or `go install go.jolheiser.com/ugit/cmd/ugitd@latest` - -Run the resulting `ugitd` binary directly, or under your process supervisor of choice (systemd, runit, etc). -µgit needs write access to its repo directory, SSH host key path, and (if generated) authorized_keys path. - -## Configuration - -µgit is configured via CLI flags, environment variables, and/or a YAML config file, in that order of precedence. - -- CLI flags use the names below, e.g. `--ssh.port=2222` -- Environment variables are the flag name upper-cased with `.` and `-` replaced by `_`, prefixed with `UGIT_`, - e.g. `ssh.port` becomes `UGIT_SSH_PORT` -- The config file (default `ugit.yaml`, override with `--config`) is YAML, with dotted flag names expanded into - nested keys, e.g. - ```yaml - ssh: - port: 2222 - ``` - -| Flag | Default | Description | -|--------------------------|-----------------------------|--------------------------------------------------------------| -| `--config` | `ugit.yaml` | Path to config file | -| `--repo-dir` | `.ugit` | Path to directory containing repositories | -| `--show-private` | `false` | Show private repos in the web interface | -| `--log.level` | `error` | Logging level: `debug`, `info`, `warn`, `error` | -| `--log.json` | `false` | Print logs in JSON(L) format | -| `--ssh.enable` | `true` | Enable the SSH server | -| `--ssh.authorized-keys` | `.ssh/authorized_keys` | Path to `authorized_keys` | -| `--ssh.clone-url` | `ssh://localhost:8448` | SSH clone URL base, shown to clients | -| `--ssh.port` | `8448` | SSH port | -| `--ssh.host-key` | `.ssh/ugit_ed25519` | SSH host key path (created if it doesn't exist) | -| `--http.enable` | `true` | Enable the HTTP server | -| `--http.clone-url` | `http://localhost:8449` | HTTP clone URL base, shown to clients | -| `--http.port` | `8449` | HTTP port | -| `--meta.title` | `ugit` | App title, shown in the web interface | -| `--meta.description` | `Minimal git server` | App description, shown in the web interface | -| `--profile.username` | | Username shown on the index page | -| `--profile.email` | | Email shown on the index page | -| `--profile.links` | | `name,url` pair for the index page; repeat the flag for more | - -Each repository also has its own `private` flag, which is just a tag on the repo and is set to `true` by default when a repo is created. -It has no effect on its own; `--show-private` is what decides whether repos tagged `private` are shown in the web interface, and it also defaults to `false`. -Out of the box, newly created repos are private and `--show-private` is off, meaning repos are hidden from the web UI by default until you opt in one way or the other. -Neither setting affects SSH access: any user in `authorized_keys` can always push/pull a repo, private or not. - -### Running public and private instances - -The setup I run is two `ugit` instances pointed at the same `--repo-dir`: - -- a **public** instance with `--show-private=false` (the default), reverse-proxied to the internet -- a **private** instance with `--show-private=true`, reachable only over Tailscale (or another private network) - -Both instances see the same repositories, but only the private instance's web UI will list/serve repos marked `private`. -Pushing/cloning over SSH is unaffected by `--show-private`, it only gates the web interface. - ## Getting your public SSH keys from another forge Using GitHub as an example (although Gitea/GitLab should have the same URL scheme)