vitrine

add README; switch unit file to systemd user-unit shape

commit 1a5958b537141fb7ca6a5e10a7c720adba550d61 · parent 8af31ec12b · browse this tree
Ximianth, 2026-07-28 14:07:54 UTC

Deployment story is now: user unit in ~/.config/systemd/user plus
loginctl enable-linger, binary in ~/bin, config per-realm
(e.g. ~/fusion/.vitrine.cfg).  No root anywhere in the happy path.
The README documents the config format and the expose-git caveats
(vitrine writes into .git; dumb-HTTP clones can be silently stale).
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..4690008
--- /dev/null
+++ b/README.md
@@ -0,0 +1,96 @@
+vitrine
+=======
+
+A tiny read-only webserver for putting local source trees on display.
+
+Point it at some directories via a small config file, and it serves them:
+markdown renders to HTML, directories become listings,
+and `?fmt=raw` on any URL serves the file bytes directly.
+No javascript required, no uploads, no auth, no dynamic anything beyond rendering.
+
+Config
+------
+
+vitrine takes exactly one config file, via the required `-config` flag
+(there is no default location and no search).
+The format is YAML:
+
+```yaml
+exhibits:
+  moonshot-1:
+    path: moonshot-1
+  meta/research/some-topic:
+    path: ../elsewhere/some-topic
+  some-repo:
+    path: ../src/some-repo
+    expose-git: true
+```
+
+- `exhibits` maps URL prefixes to directories.
+  A prefix may contain slashes; the intermediate URL levels then serve synthetic listings
+  that reveal only the mounted subtrees.
+- `path` (required) is the directory to serve.
+  Relative paths resolve against the config file's directory,
+  which makes a config portable alongside the trees it describes.
+  Absolute paths also work.
+- `expose-git` (optional, default false): see below.
+
+A bad config (parse error, unknown key, missing path, or zero exhibits)
+is a startup error: vitrine refuses to run rather than serve the wrong thing.
+
+expose-git
+----------
+
+By default, `.git` directories are invisible: hidden from listings and unreachable by direct URL.
+
+Setting `expose-git: true` on an exhibit flips that:
+`.git` lists and serves like any other directory,
+which makes `git clone http://host/exhibit/.git` work over git's dumb HTTP transport.
+
+Two caveats, read them before enabling:
+
+- **vitrine writes into that exhibit's `.git`.**
+  Dumb-HTTP clone requires `.git/info/refs` and `.git/objects/info/packs`,
+  and ordinary commits never maintain them,
+  so vitrine runs `git update-server-info` on the exhibit at startup.
+  This is a deliberate exception to vitrine's otherwise strictly read-only stance.
+- **Dumb HTTP has dumb semantics.**
+  Clones reflect the refs as of the last `update-server-info` run,
+  so commits made after vitrine started are invisible to clones until it next runs
+  (currently: restart vitrine).
+  A stale clone succeeds silently at the old tip; there is no warning.
+  Concurrent `git gc` in the exhibit can also break an in-flight clone (loudly; retry works).
+
+Deployment
+----------
+
+Run vitrine as your own user, under a systemd user unit.  No root anywhere.
+
+1. Build and install the binary somewhere on your user's path:
+
+   ```
+   go build -o ~/bin/vitrine .
+   ```
+
+2. Write your config, e.g. `~/fusion/.vitrine.cfg`,
+   with paths relative to that directory (see Config above).
+
+3. Install the unit file from this repo as a *user* unit:
+
+   ```
+   mkdir -p ~/.config/systemd/user
+   cp vitrine.service ~/.config/systemd/user/
+   systemctl --user daemon-reload
+   systemctl --user enable --now vitrine
+   ```
+
+   Adjust `ExecStart` in the unit if your binary or config live elsewhere.
+
+4. Keep it running after logout (user units otherwise stop with your session):
+
+   ```
+   loginctl enable-linger $USER
+   ```
+
+Check on it with `systemctl --user status vitrine`
+and `journalctl --user -u vitrine -f`.
diff --git a/vitrine.service b/vitrine.service
index 6325d0b..d7bcb28 100644
--- a/vitrine.service
+++ b/vitrine.service
@@ -1,11 +1,10 @@
 [Unit]
-Description=vitrine: tiny read-only web viewer for fusion source trees
+Description=vitrine: tiny read-only web viewer for local source trees
 After=network.target
 
 [Service]
-ExecStart=/usr/local/bin/vitrine -addr :8000
-User=exedev
+ExecStart=%h/bin/vitrine -addr :8000 -config %h/fusion/.vitrine.cfg
 Restart=on-failure
 
 [Install]
-WantedBy=multi-user.target
+WantedBy=default.target