Self-Hosted Git as Document Infrastructure

I use an OpenBSD server as the center of a Git-backed Markdown system. It stores the canonical copy of my vault, accepts edits from my computers and phone, and runs automation that creates and updates Markdown documents.

The important part is that human-written notes and generated documents use the same repository and the same history.

The architecture

Architecture of the Git-backed Markdown system: Windows, Ubuntu, and iPhone clients synchronize with a canonical bare Git repository on an OpenBSD server; a post-receive hook maintains a separate vault work tree used by NRE automation jobs.

The server hosts a bare Git repository and maintains a separate checked-out copy for automation. My devices are ordinary Git clients: I edit locally and sync changes back to the server, while automated jobs write into the server-side copy, commit their results, and send those changes back out to my devices.

The flow works in both directions:

client edit → Git → server

server automation → Git → client

Why Git?

Markdown files already work well with Git, which gives me:

  • complete local copies on every device;
  • version history;
  • explicit synchronization;
  • recoverable conflicts;
  • one transport mechanism for both manual and generated documents.

A report created by automation is simply another Markdown file in the repository, so it does not need a separate publishing or synchronization system.

Markdown first, Obsidian second

I use Obsidian as the main interface to the vault, but the infrastructure itself only needs to understand files and Git. The server can generate reports, update dashboards, or import documentation without running a graphical editor.

Obsidian stays on the devices where I actually read and write notes. Keeping that boundary also means I could change editors without changing the underlying system.

Why not Obsidian Sync?

Obsidian Sync is a much simpler solution if the goal is simply to keep an Obsidian vault synchronized across devices. My setup also uses the server for unattended automation, so making Obsidian part of the server-side architecture would mean adding a desktop application and Electron runtime to a machine that otherwise only needs Git and ordinary command-line tools.

Using Git instead lets the server remain small and headless while keeping the Markdown independent of the application I use to edit it.

Automation becomes publishing

The server-side work tree gives automated jobs somewhere to write. A job can gather information, generate a Markdown report, save it into the vault, and commit the result. The next time a client synchronizes, that report appears alongside everything else.

This also works for material maintained outside the vault. Project documentation can remain authoritative in its own repository while selected documents are projected into the vault for reference. The vault can therefore contain both manually written notes and documents maintained by other systems without requiring a separate distribution mechanism.

The supporting tools

I built a few tools around this architecture:

  • vaultctl handles client synchronization and controlled document projection;
  • NRE runs Markdown-generation jobs;
  • OpenBSD and Git provide the server-side foundation.

The implementation has more machinery around synchronization, repository layout, hooks, recovery, and automation, but the basic model is simple: people write Markdown, software writes Markdown, and Git carries both through the same history.

The companion articles Inside My Git-Backed Markdown Infrastructure and Client Operations in a Git-Backed Markdown Vault cover the server-side implementation and day-to-day client synchronization in more detail.