gitpages

A collection of scripts to securely webhost and publish git repositories.
git clone https://scm.kuandu.systems/git-raw/gitpages.git
Log | Files | Refs | README | LICENSE

commit 6e9b0998404a87809bcafab68c008fd57d464d95
parent bd078d1b5d295a6c6192a8ad750e5d68c594b346
Author: Fred Großkopf <fred@kuandu.systems>
Date:   Thu, 14 May 2026 23:45:38 +0200

Updates README

Diffstat:
MREADME.md | 121++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 68 insertions(+), 53 deletions(-)

diff --git a/README.md b/README.md @@ -1,87 +1,102 @@ # Gitpages -Gitpages is a minimalist static site generator for Git repositories on OpenBSD. -It mirrors bare repositories into a web-accessible directory and generates -browsable HTML using [stagit](https://codemadness.org/stagit). +Gitpages is a small static site generator for bare Git repositories on OpenBSD. +It mirrors bare repositories into a web directory and generates HTML with +[stagit](https://codemadness.org/stagit). -Updates run asynchronously via a queue and a dedicated service user, keeping Git -hooks fast and safe. +Updates run through a queue and a dedicated service user, keeping Git hooks fast +and the setup more secure. -## How it works +## Layout +```txt +push by git user + -> post-receive hook + -> queue file -1. A developer pushes to a bare repository. -2. The post-receive hook writes the repository path into a queue file. -3. A cron job (running as `_gitpages`) processes queued jobs: - - Mirrors the repository into `GIT_RAW` - - Generates HTML into `GIT_HTML` using stagit -4. httpd serves both: - - Raw repositories (for cloning) - - Generated HTML (for browsing) +gitpages-update.sh by _gitpages via cron + -> mirror GIT_SRC to GIT_RAW under WEB_ROOT + -> generate HTML in GIT_HTML under WEB_ROOT -```txt -Push → post-receive → queue → cron mirrors → stagit → httpd serves both raw repos + HTML +httpd serves WEB_ROOT as www ``` -## Example layout +Example: ```txt -https://scm.example.com/ -├── git/ ← HTML browsing (stagit) +/var/www/htdocs/scm.example.site/ +├── git/ │ └── myrepo/ -└── git-raw/ ← HTTP clone +└── git-raw/ └── myrepo.git ``` ## Components -**Component** | **Description** --- | -- -`install.sh` | Sets up users, cron, directories, config -`uninstall.sh` | Removes service user, cron, directories, log rotation -`gitpages-init-repos.sh` | Prompts repo metadata, installs hooks -`post-receive.hook` | Writes repo path to queue on push -`gitpages-mirror-git.sh` | Copies repos + `update-server-info` -`gitpages.sh` | stagit HTML generation -`gitpages-update.sh` | Queue processor (cron) -`gitpages-regenerate.sh` | Full rebuild - +- `install.sh` sets up users, directories, cron, and config. +- `uninstall.sh` removes the service setup. +- `gitpages-init-repos.sh` installs metadata and hooks for repositories. +- `post-receive.hook` queues repository updates. +- `gitpages-mirror-git.sh` mirrors bare repositories. +- `gitpages.sh` generates stagit HTML. +- `gitpages-update.sh` processes the queue. +- `gitpages-regenerate.sh` rebuilds everything. ## Quick start ```sh doas pkg_add git stagit -doas ./install.sh git # "git": user that owns the git repos -doas vi /etc/gitpages.conf -doas -u git ./gitpages-init-repos.sh /home/git/repos -doas -u _gitpages -s /bin/sh ./gitpages-regenerate.sh +doas ./install.sh git /home/git/public-repos /var/www/htdocs/scm.example.site +doas -u git ./gitpages-init-repos.sh +doas -u _gitpages ./gitpages-regenerate.sh ``` -## Configuration (/etc/gitpages.conf) - -```ini -GIT_SRC=/var/git/repos # Source bare repos (*.git) -WEB_ROOT=/var/www/htdocs/scm.example.com # httpd document root -GIT_RAW=git-raw # Raw repos subdirectory -GIT_HTML=git # HTML output subdirectory -ASSETS_DIR=/var/gitpages/assets # Static files (CSS/JS) copied to repo pages -INDEX_TITLE=My Git repositories # Index.html <title> -INDEX_DESCRIPTION=... # Index.html description -REPO_TITLE_DESCRIPTION= - My Project # Replaces "- DESCRIPTION" in "File - REPO - DESCRIPTION" -``` +## Configuration + +`/etc/gitpages.conf`: + +- `GIT_SRC`: source directory containing bare repositories. +- `WEB_ROOT`: required document root for httpd. +- `GIT_RAW`: subdirectory for mirrored repos. +- `GIT_HTML`: subdirectory for generated HTML. +- `ASSETS_DIR`: optional static files for repo pages. +- `INDEX_TITLE`: optional title for `index.html`. +- `INDEX_DESCRIPTION`: optional description for `index.html`. +- `REPO_TITLE_DESCRIPTION`: optional repo title suffix. + +Defaults written by `install.sh`: + +- `GIT_RAW=git-raw` +- `GIT_HTML=git` +- `ASSETS_DIR=/var/gitpages/assets` + ## httpd ```httpd -server "scm.example.com" { +server "scm.example.site" { listen on * port 80 - root "/htdocs/scm.example.com" + root "/htdocs/scm.example.site" location "/git/*" { directory auto index } + location "/git-raw/*" { directory auto index } } ``` ## Notes -- Failed jobs stay queued for retry -- Logs: `/var/log/gitpages/update.log` -- `ls /var/spool/gitpages/queue | wc -l` = pending jobs -- One runner at a time (lockfile) +- Edit `/etc/gitpages.conf` to set page metadata or change paths. +- When a new bare repository is added to `GIT_SRC`, run `gitpages-init-repos.sh` for it. +- By default, `gitpages-update.sh` runs from `_gitpages` cron every 5 minutes. +- Logs are written to `/var/log/gitpages/update.log`. +- Pending jobs are in `/var/spool/gitpages/queue`. + +## Security + +- The post-receive hook only writes entries to `/var/spool/gitpages/queue/`. +- The queue directory is restricted to the `gitpages` group. +- Failed jobs stay queued for retry. +- `_gitpages` is a service user with no login shell. +- `_gitpages` performs mirroring and HTML generation. +- `httpd` serves only the generated files under `WEB_ROOT`. +- `WEB_ROOT` is owned by `root:wheel`; only the generated subdirectories are writable by `_gitpages`. +- The `git` user must have read access to `GIT_SRC`. +- Source repositories and public web output are kept separate.