microgit-server

中文文档
0.4.2发布于 2026/11/04MITES Module

Git smart HTTP server with per-account repositories, SQLite accounts, templates and an audit trail

原始使用文档
文档目录17 节
  1. Requirements
  2. Install
  3. Run the server
  4. CLI (companion package)
  5. What lives on disk
  6. Source layout
  7. Overview
  8. Landing page
  9. Repository page
  10. Administrators
  11. API reference
  12. Audit trail
  13. settings.json
  14. Using a domain instead of the IP
  15. Environment variables (overrides)
  16. Troubleshooting
  17. npm package

microgit

A small Git smart-HTTP server written in TypeScript. Every repository belongs to an account and is addressed as /<user>/<repository>.git, so two people can each have their own app without colliding. Accounts, sessions and the audit trail live in SQLite, the HTTP layer is Express, and signing in keeps a server side session in an HttpOnly cookie.

Requirements

  • Node.js 24+ (uses the built-in node:sqlite)
  • git in PATH
  • bash only for running the test suite

Install

npm install -g microgit-server

Run the server

microgit-server                  # uses settings.json in the current directory
microgit-server --settings       # open the interactive settings editor
microgit-server -s               # shorthand for --settings
microgit-server settings         # same as --settings

From a source checkout:

npm run dev                      # auto-reload (tsx watch)
npm test                         # end-to-end suite (127 checks)

The --settings flag opens a terminal menu to edit settings.json: pick a setting by number, enter a new value, or press h for a help screen describing every option. Press 0 to save and exit, q to discard.

CLI (companion package)

The microgit-cli package is a first-class part of this project: it is the recommended way to drive the server day to day. It keeps your session, creates and deletes repositories, and wraps git so push and pull use your account credentials automatically. Published separately so it can be installed on any machine that talks to the server:

npm install -g microgit-cli
microgit login --url http://127.0.0.1:3000 --save-password
microgit new app --init
cd app
microgit commit -m "First change"

See cli/README.md for every command, the config file and how the API token differs from the git password. Every command the server exposes (register, login, new, delete, list, clone, push, pull, whoami, audit, ...) is reachable through it, and it stores the session token and git password in ~/.microgit/config.json. The cli/ folder in this repository is the source of that package; to work on it locally run npm install && npm run build inside it.

What lives on disk

repos/<sha256(user + "\n" + name)>/<name>.git   bare repository
data/users.db                                   accounts, sessions, audit trail
data/repo.db                                    repository catalogue and owners
settings.json                                   server settings (admin only)

The hash is an internal folder name and is never returned by the API. A URL, a listing entry and every error message speak in owner/name terms only.

Source layout

src/index.ts            settings, storage, sessions, listen, shutdown
src/config/             settings.json + env overrides, paths, MOTD, version
src/data/               SQLite connections and schemas, audit trail, TTL cache
src/accounts/           users and administrators, session lifecycle
src/repositories/       naming, storage catalogue, create, delete
src/git/                git URL parsing, git http-backend, repository inspection
src/http/               Express app, dispatcher, request/response/session helpers
src/http/handlers/      one module per endpoint group (auth, account, repos, ...)
src/http/pages/         server rendered landing/repository pages, markdown, HTML escaping
src/security/           scrypt passwords, tokens, Basic/Bearer header parsing
src/settings-cli.ts     interactive settings editor (terminal UI)

Overview

  • Accounts — POST /api/register creates one; the first account becomes an administrator. Registration stays open until allowRegistration is set to false in settings.json.
  • Sessions — POST /api/login returns a token and an HttpOnly sid cookie; GET /api/me reports the current account; POST /api/logout revokes. Tokens expire after sessionDays days.
  • Repositories — POST /api/new creates owner/name (lower-cased, slugified); POST /api/delete or DELETE /api/repos/<owner>/<name> removes one. Push always authenticates with the account username and password; private repositories hide reads from everyone but the owner and administrators.
  • Listing — GET /api/repos with owner, name, private, page and limit (max 200) filters.
  • Audit trail — every create, delete, registration, login, logout, push and refused read is recorded in users.db; administrators read it via GET /api/audit?format=json|html.
  • Accounts admin — GET /api/users and PATCH /api/users/<username> (admin only) list and toggle the admin flag. Admin rights live only in users.is_admin; editing settings.json never promotes an account. The last administrator cannot be demoted. If no administrator exists (restored database), the oldest account is promoted at startup.
  • MOTD — motd in settings.json is returned after sign-in and by GET /api/settings; it is a greeting for CLI and terminal clients and is never shown on the landing page.

Detailed request/response examples will be published in a separate document.

Landing page

GET / is a small HTML page rather than JSON: it shows the server brand, the configured MOTD, the sign-in command and the clone URL to use. Every address in it comes from domain or publicUrl when one of them is set, so you can browse and copy the clone URL without hand-editing the IP.

Repository page

http://<host>/<user>/<repository>/ opens the web view of a repository (the trailing slash is canonical; without it the server redirects). Nothing extra is stored for it: the page reads the bare repository with plain git commands.

  • Title, privacy badge, commit count and the repository size on disk, with the repository identified as [email protected].
  • The clone URL behind the Git URL button, ready to copy.
  • The newest commit plus one row per entry, each with the last commit that touched it. Every directory and file is a real link: /<user>/<repo>/tree/<dir>/ lists a directory and /<user>/<repo>/blob/<file> shows the file, with ?raw=1 for plain text.
  • README.md (or README.markdown) of the directory being viewed, rendered as markdown; ?raw=1 shows the same file as plain text, so neither view can inject HTML into the page.
  • An empty repository still renders, with the git clone hint.

All of it is read from git on the request: nothing is cached in a template or sent as static HTML.

Git URLs keep working next to the page: git clone uses the protocol paths below /alice/app.git (info/refs, git-upload-pack, …), which git http-backend still handles. Opening the bare clone URL in a browser redirects to the page, so /alice/app.git lands on /alice/app/ instead of a blank response. A private repository's page answers 404 unless the owner or an administrator is signed in with a session cookie. Markdown is rendered by a small built-in renderer (headings, paragraphs, lists, quotes, code, links, bold, italics, images, tables, task lists, strikethrough, callouts) — no dependency was added for it.

Administrators

Admin rights live in one place only: users.is_admin in data/users.db. There is no settings key that can grant them, so editing settings.json never promotes an account. The first account created on a fresh server is an administrator.

  • Only the owner of an admin account may list accounts or change the flag (403 otherwise); the change is audited as user.admin and applies to the next request, because cached sessions are cleared.
  • The last administrator cannot be demoted (409); otherwise nobody could delete repositories or read the audit trail.
  • If the database ends up with no administrator at all (restored or imported users.db), the oldest account is promoted at startup and the log says so.

API reference

MethodPathAuthPurpose
POST/api/register—Create an account, returns a session token
POST/api/login—Exchange username/password for a token
POST/api/logoutSessionRevoke the session and clear the cookie
GET/api/meSessionCurrent account and MOTD
POST/api/newSessionCreate a repository
POST/api/deleteSessionDelete a repository
DELETE/api/repos/<owner>/<name>SessionDelete a repository (REST)
GET/api/repos—List repositories
GET/api/repos/<owner>/<name>—One repository
GET/api/settings—Public settings
GET/api/usersSession (admin)Every account and its admin flag
PATCH/api/users/<username>Session (admin)Grant or revoke the admin flag
GET/api/audit?format=json|htmlSession (admin)Audit trail
GET/—HTML landing page (brand, MOTD, clone URL)
GET/<owner>/<name>/—Repository page (?raw=1 for plain README)
GET/health—Liveness and counts
GET/metrics—Counts, cache and memory numbers

"Session" means the sid cookie set by login, or an Authorization: Bearer <token> header for scripts. Git pushes use HTTP Basic with the account password instead.

Errors are JSON: {"error":"..."}. 400 invalid input, 401 no/expired session, 403 wrong account, 404 unknown repository, 409 name conflict, 413 body too large.

Audit trail

Every create, delete, registration, login, logout, push and refused read is recorded in users.db with time, actor, repository, status code, IP and detail. Administrators can read it. Passwords and tokens are never written to the audit trail, and only their hashes are stored in the database.

settings.json

Created on first start; edit it on the server, there is no HTTP endpoint for it. Run microgit-server --settings (or -s) for an interactive terminal editor, or edit the file directly.

KeyDefaultMeaning
host"127.0.0.1"Bind address (loopback keeps it private)
brand"litegit"Name in the page header, the HTML title and the footer
tagline""Word after the brand in the header; empty shows only the brand
port3000TCP port to listen on
reposDir"repos"Where bare repositories are stored
dataDir"data"Where the SQLite files are stored
publicUrl""Full origin used in clone URLs and generated links; empty = derive from the request
domain""Public domain shown in the UI instead of the IP; git.example.com or https://git.example.com
trustProxyfalseRead X-Forwarded-Proto/Host/For from a reverse proxy
motd""Banner shown after signing in; empty = none
allowRegistrationtrueAllow POST /api/register
template""Folder copied into every new repository
sessionDays7API session lifetime
maxPushBytes0Maximum size of one pushed pack (0 = unlimited)
cacheTtlMs5000In-memory lookup cache TTL

host, port, reposDir, dataDir, publicUrl and domain are read once at startup, so restart after changing them (the data directories especially cannot move while their databases are open). motd, template, brand, tagline, allowRegistration, sessionDays, maxPushBytes and cacheTtlMs are read per request and apply immediately.

Using a domain instead of the IP

Set domain when the server is reached through a hostname, so the clone buttons, copy field, links and API responses show the domain instead of whatever address the request arrived on:

{
  "domain": "git.example.com"
}

A bare host is assumed to be HTTP; write the scheme explicitly when the server is behind TLS:

{
  "domain": "https://git.example.com"
}

Precedence for the public origin is PUBLIC_URL (environment) → publicUrl → domain → the request's Host header. That means you only need one of publicUrl or domain; if publicUrl is already set, it wins. Restart the server after changing either one.

Environment variables (overrides)

Everything above belongs in settings.json. The environment only overrides it, which is handy for containers and throwaway runs:

VariableDefaultMeaning
PORT, HOST3000, 127.0.0.1Listen address
GIT_REPOS_DIRreposWhere bare repositories are stored
GIT_DATA_DIRdataWhere the SQLite files are stored
GIT_SETTINGS_FILEsettings.jsonSettings file path
PUBLIC_URLemptyOrigin used in clone URLs; wins over domain
TRUST_PROXY0Read X-Forwarded-Proto/Host/For from a reverse proxy

Troubleshooting

  • Authentication failed on push — use the account username/password, not a token.
  • 401 after login in a script — pass the session cookie or a Bearer token; curl does not keep the sid cookie between calls by itself.
  • Repository not found — owner and name are case-sensitive after normalization; check the listing endpoint.
  • Port already in use — set PORT or change port in settings.json.

npm package

The server is published as the microgit-server npm package (see Install above for the install command). After installation the microgit-server binary is available:

microgit-server                 # start the server (uses settings.json in CWD)
microgit-server --settings      # open the interactive settings editor
microgit-server -s              # shorthand for --settings
microgit-server settings        # same as --settings

The --settings flag opens a terminal menu to edit settings.json: pick a setting by number, enter a new value, or press h for a help screen describing every option. Press 0 to save and exit, q to discard.

The companion command line client is a separate package: npm install -g microgit-cli.

版本与发布记录

microgit-server 共发布 3 个版本,首次发布于 2026/11/04;过去 12 个月发布了 3 个版本。

版本发布日期距今
0.4.2latest2026/11/04今天
0.4.12026/11/04今天
0.0.0-stage2026/11/04今天

关于 microgit-server 的常见问题

microgit-server 是什么?

Git smart HTTP server with per-account repositories, SQLite accounts, templates and an audit trail

如何安装 microgit-server?

在项目目录运行 npm install microgit-server,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 microgit-server,可以用 npx microgit-server 直接运行。

microgit-server 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/microgit-server 是否存在。

microgit-server 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

microgit-server 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

microgit-server 可以商用吗?

microgit-server 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

microgit-server 还在维护吗?

最新版本 0.4.2 发布于 2026/11/04(今天);至今共发布 3 个版本,其中过去 12 个月发布了 3 个;首次发布于 2026/11/04。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。