char/sorcery

static-files based git repo viewer

git clone https://git.t4t.associates/char/sorcery

Charlotte Somremove --allow-all from ngx script1acdf74

main
3.3 KiB120 linesraw

sorcery

tiny read-only git repo viewer

  • point at a dir containing user/repo bare git repos
  • generates static sites for every repo
  • serves via nginx (or other proxy supporting the X-Accel headers)
  • progressively enhances via js to provide dynamic content (commit diffs, tree-at-revision, etc)
  • syntax highlighting via arborium (both serverside and clientside)
  • supports "git smart HTTP" for read-only clones

pairs well with ssh git for read-write access

usage

compiles to a static executable (linux musl) on the default package in the flake:

nix build

install it as /usr/local/bin/sorceryd or whatever

nginx

production nginx config generated via @char/ngx:

deno run sorcery.ngx.ts > sorcery.conf

systemd

Example /etc/systemd/system/sorceryd.service:

[Unit]
Description=Sorcery Git forge
After=network.target

[Service]
Type=simple
User=git
Group=git
RuntimeDirectory=sorcery
CacheDirectory=sorcery
ConfigurationDirectory=sorcery
EnvironmentFile=/etc/sorcery/env
ExecStart=/usr/local/bin/sorceryd
Restart=on-failure
RestartSec=2
UMask=0027
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only

[Install]
WantedBy=multi-user.target

With /etc/sorcery/env:

SORCERY_REPOSITORIES=/home/git/public
SORCERY_CACHE=/var/cache/sorcery
SORCERY_SOCKET=/run/sorcery/sock
SORCERY_INSTANCE_NAME=my-cool-git.example
SORCERY_CLONE_URL_BASE=https://my-cool-git.example
SORCERY_REFRESH_TOKEN_FILE=/etc/sorcery/refresh-token

Command-line flags remain available and override the corresponding environment variables.

ssh

sorcery-ssh is an sshd ForceCommand that provides read-write git access. it auto-creates bare repositories on first push (like sourcehut) and also provides commands + an optional interactive tui for editing the description of a repo.

nix build .#sorcery-ssh
nix build .#sorcery-ssh-tui # optional

install sorcery-ssh (and sorcery-ssh-tui), ensure the git user can read /etc/sorcery/refresh-token, and add the following to sshd_config:

Match User git
  SetEnv SORCERY_REPOSITORIES=/home/git/public SORCERY_SOCKET=/run/sorcery/sock SORCERY_REFRESH_TOKEN_FILE=/etc/sorcery/refresh-token SORCERY_CLONE_URL_BASE=https://my-cool-git.example SORCERY_INSTANCE_NAME=my-cool-git.example SORCERY_SSH_TUI=/usr/local/bin/sorcery-ssh-tui
  ForceCommand /usr/local/bin/sorcery-ssh

optional: push refresh

since this is a static-files-based viewer, repositories need updating when their state changes. if you're using sorcery-ssh, repositories will automatically refresh after a git receive-pack. otherwise, you can use a post-receive hook like so:

#!/usr/bin/env sh

repo=$(basename "$PWD" .git)
user=$(basename "$(dirname "$PWD")")
token=$(cat /etc/sorcery/refresh-token)
exec curl -fsS --unix-socket /run/sorcery/sock \
  -H "Authorization: Bearer $token" \
  -X POST "https://my-cool-git.example/-/refresh/$user/$repo"

in any case, sorceryd's scanner will pick changes up eventually, so this is optional

development

cd web && deno task check && deno task test && deno task build
cd .. && cargo test

since we embed the frontend inside the executable, you must generate the frontend bundle before running a cargo build.

1# sorcery
2
3tiny read-only git repo viewer
4
5- point at a dir containing `user/repo` bare git repos
6- generates static sites for every repo
7- serves via nginx (or other proxy supporting the `X-Accel` headers)
8- progressively enhances via js to provide dynamic content (commit diffs, tree-at-revision, etc)
9- syntax highlighting via arborium (both serverside and clientside)
10- supports "git smart HTTP" for read-only clones
11
12pairs well with ssh git for read-write access
13
14## usage
15
16compiles to a static executable (linux musl) on the default package in the flake:
17
18```sh
19nix build
20```
21
22install it as `/usr/local/bin/sorceryd` or whatever
23
24## nginx
25
26production nginx config generated via [`@char/ngx`](https://jsr.io/@char/ngx):
27
28```sh
29deno run sorcery.ngx.ts > sorcery.conf
30```
31
32## systemd
33
34Example `/etc/systemd/system/sorceryd.service`:
35
36```ini
37[Unit]
38Description=Sorcery Git forge
39After=network.target
40
41[Service]
42Type=simple
43User=git
44Group=git
45RuntimeDirectory=sorcery
46CacheDirectory=sorcery
47ConfigurationDirectory=sorcery
48EnvironmentFile=/etc/sorcery/env
49ExecStart=/usr/local/bin/sorceryd
50Restart=on-failure
51RestartSec=2
52UMask=0027
53NoNewPrivileges=true
54PrivateTmp=true
55ProtectSystem=strict
56ProtectHome=read-only
57
58[Install]
59WantedBy=multi-user.target
60```
61
62With `/etc/sorcery/env`:
63
64```sh
65SORCERY_REPOSITORIES=/home/git/public
66SORCERY_CACHE=/var/cache/sorcery
67SORCERY_SOCKET=/run/sorcery/sock
68SORCERY_INSTANCE_NAME=my-cool-git.example
69SORCERY_CLONE_URL_BASE=https://my-cool-git.example
70SORCERY_REFRESH_TOKEN_FILE=/etc/sorcery/refresh-token
71```
72
73Command-line flags remain available and override the corresponding environment variables.
74
75## ssh
76
77`sorcery-ssh` is an sshd `ForceCommand` that provides read-write git access.
78it auto-creates bare repositories on first push (like sourcehut)
79and also provides commands + an optional interactive tui for editing the description of a repo.
80
81```sh
82nix build .#sorcery-ssh
83nix build .#sorcery-ssh-tui # optional
84```
85
86install `sorcery-ssh` (and `sorcery-ssh-tui`), ensure the `git` user can read `/etc/sorcery/refresh-token`, and add the following to `sshd_config`:
87
88```sshconfig
89Match User git
90  SetEnv SORCERY_REPOSITORIES=/home/git/public SORCERY_SOCKET=/run/sorcery/sock SORCERY_REFRESH_TOKEN_FILE=/etc/sorcery/refresh-token SORCERY_CLONE_URL_BASE=https://my-cool-git.example SORCERY_INSTANCE_NAME=my-cool-git.example SORCERY_SSH_TUI=/usr/local/bin/sorcery-ssh-tui
91  ForceCommand /usr/local/bin/sorcery-ssh
92```
93
94## optional: push refresh
95
96since this is a static-files-based viewer, repositories need updating when their state changes.
97if you're using `sorcery-ssh`, repositories will automatically refresh after a `git receive-pack`.
98otherwise, you can use a post-receive hook like so:
99
100```sh
101#!/usr/bin/env sh
102
103repo=$(basename "$PWD" .git)
104user=$(basename "$(dirname "$PWD")")
105token=$(cat /etc/sorcery/refresh-token)
106exec curl -fsS --unix-socket /run/sorcery/sock \
107  -H "Authorization: Bearer $token" \
108  -X POST "https://my-cool-git.example/-/refresh/$user/$repo"
109```
110
111in any case, sorceryd's scanner will pick changes up eventually, so this is optional
112
113## development
114
115```sh
116cd web && deno task check && deno task test && deno task build
117cd .. && cargo test
118```
119
120since we embed the frontend inside the executable, you **must** generate the frontend bundle before running a `cargo build`.