microgit
一个用TypeScript编写的小型Git智能http服务器。每个存储库都属于
账户,地址为 /<user>/<repository>.git,所以两个人可以各自拥有
他们自己的 app 没有碰撞。帐户、会话和审计跟踪存在于
在SQLite中,HTTP层是Express,并且登录将服务器端会话保持在一个
HttpOnly 饼干。
需求
- Node.js 24+(使用内置的
node:sqlite) git在PATHbash仅用于运行测试套件
安装
npm install -g microgit-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
从源代码签出:
npm run dev # auto-reload (tsx watch)
npm test # end-to-end suite (127 checks)
这个 --settings Flag打开一个终端菜单进行编辑 settings.json选一个
按号码设置,输入新的数值,或按 h 获取描述的帮助屏幕
每一个选择。新闻 0 要保存并退出, q 抛弃。
CLI(配套包)
这个 microgit-cli 包是这个项目的头等部分:它是
每天驱动服务器的推荐方法。它保持你的会话,创造
删除存储库和包装 git 所以推拉用你的账号
自动凭证。单独发布,所以它可以安装在任何
与服务器通信的机器:
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"
看到 cli/README.md 对于每个命令,配置文件以及如何
API令牌与git密码不同。服务器公开的每个命令
(注册,登录,新建,删除,列表,克隆,推送,拉取,whoami,审计,…
可通过它访问,它将会话令牌和git密码存储在
~/.microgit/config.json。这个 cli/ 的源代码
这包;在本地运行 npm install && npm run build 在里面。
磁盘上有什么
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)
哈希值是一个内部文件夹名称,为 从来没有 由API返回。一个URL,
一个清单条目和每个错误消息都在说话 owner/name 条款。
源的布局
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)
概述
- 账户 - - - - - -
POST /api/register创建一个;第一个帐户变成 管理员。报名时间截止至allowRegistration设为false在settings.json。 - 会话 - - - - - -
POST /api/login返回一个令牌和一个HttpOnlysid饼干;GET /api/me报告往来帐;POST /api/logout撤销。令牌 到期后sessionDays天。 - 存储库 - - - - - -
POST /api/new创建owner/name(小写,slugified);POST /api/delete或DELETE /api/repos/<owner>/<name>删除一个。推 始终使用帐户的用户名和密码进行身份验证;私人 除了所有者和管理员之外,存储库对所有人隐藏读取。 - 清单 - - - - - -
GET /api/repos与owner,name,private,page和limit(最多200个)过滤器。 - 审计跟踪 -每个创建,删除,注册,登录,注销,推送和
拒绝读取记录在
users.db;管理员通过GET /api/audit?format=json|html。 - 账户管理 - - - - - -
GET /api/users和PATCH /api/users/<username>(管理 只有)列表和切换管理标志。管理员权限只存在于users.is_admin;编辑settings.json从不推销一个帐户。最后一个 管理员不能被降级。如果不存在管理员(已恢复的数据库), 最老的帐户在启动时被提升。 - 公告 - - - - - -
motd在settings.json签到后还回来吗GET /api/settings;它是对CLI和终端客户端的一种问候,永远不会 显示在登陆页面上。
详细的请求/回应示例将在另一份文件中公布。
着陆页
GET / 是一个小的HTML页面,而不是JSON:它显示服务器的品牌,
配置的MOTD、登录命令和要使用的克隆URL。每个地址
它来自于 domain 或 publicUrl 当其中一个设置时,您可以浏览
并复制克隆URL,而无需手动编辑IP。
库页
http://<host>/<user>/<repository>/ 打开存储库的web视图
尾斜杠是规范的;如果没有它,服务器将重定向)。没有额外的了
为它存储:该页使用plain读取裸存储库 git 命令。
- 标题、隐私标识、提交计数和磁盘上的存储库大小
存储库标识为
[email protected]。 - 后面的克隆URL Git URL 按钮,准备复制。
- 最新提交的每个条目加一行,每一行与上次提交的相同
摸它。每个目录和文件都是一个真正的链接:
/<user>/<repo>/tree/<dir>/列出目录和/<user>/<repo>/blob/<file>显示文件,带?raw=1用于纯文本。 README.md(或README.markdown),呈现为 减价;?raw=1显示与纯文本相同的文件,因此两个视图都不能 将HTML注入页面。- 仍然呈现空存储库,并使用
git clone提示。
所有这些都是在请求时从git中读取的:没有任何东西缓存在模板或 作为静态HTML发送。
Git url一直在页面旁边工作: git clone 使用下面的协议路径
/alice/app.git (info/refs, git-upload-pack,…),哪个 git http-backend
仍需处理。在浏览器中打开裸克隆URL将重定向到该页面,因此
/alice/app.git 的土地上 /alice/app/ 而不是一个空白的回应。一个私人
存储库的页面答案 404 除非所有者或管理员已登录
使用会话cookie。Markdown由一个小的内置渲染器渲染
(标题、段落、列表、引号、代码、链接、粗体、斜体、图片、表格、
任务列表、划线、标注)——没有为其添加依赖项。
管理员
管理员权限只存在于一个地方: users.is_admin 在 data/users.db. 有
没有设置键可以授予他们,所以编辑 settings.json 从不提倡
帐户。在新服务器上创建的第一个帐户是管理员。
- 只有管理帐户的所有者可以列出帐户或更改标志(
403否则);该更改被审计为user.admin并适用于下一个 请求,因为缓存的会话被清除。 - 这个 最后 管理员不能被降级(
409); 否则没人能 删除存储库或读取审计跟踪。 - 如果数据库最终没有管理员(恢复或导入)
users.db),最老的帐户在启动时被提升,日志也会这样显示。
API参考
| 方法 | 路径 | 身份验证 | 目的 |
|---|---|---|---|
| 帖子 | /api/register | - - - - - - | 创建一个帐户,返回一个会话令牌 |
| 帖子 | /api/login | - - - - - - | 将用户名/密码交换为令牌 |
| 帖子 | /api/logout | 会话 | 撤销会话并清除cookie |
| 得到 | /api/me | 会话 | 往来账户和活期存款 |
| 帖子 | /api/new | 会话 | 创建存储库 |
| 帖子 | /api/delete | 会话 | 删除存储库 |
| 删除 | /api/repos/<owner>/<name> | 会话 | 删除存储库(REST) |
| 得到 | /api/repos | - - - - - - | 存储库列表 |
| 得到 | /api/repos/<owner>/<name> | - - - - - - | 一个库 |
| 得到 | /api/settings | - - - - - - | 公共设置 |
| 得到 | /api/users | 会话(管理) | 每个帐户及其管理标志 |
| 补丁 | /api/users/<username> | 会话(管理) | 授予或撤销管理标志 |
| 得到 | /api/audit?format=json|html | 会话(管理) | 审计跟踪 |
| 得到 | / | - - - - - - | HTML登陆页(品牌、MOTD、克隆URL) |
| 得到 | /<owner>/<name>/ | - - - - - - | 资料库页面(?raw=1 (简单的README) |
| 得到 | /health | - - - - - - | 活力与计数 |
| 得到 | /metrics | - - - - - - | 计数、缓存和内存数量 |
“会话”是指 sid 通过登录设置的Cookie,或者 Authorization: Bearer <token>
脚本头。Git推送使用HTTP Basic和帐户密码。
错误是JSON: {"error":"..."}。 400 无效的输入, 401 没有/过期
会话, 403 错误的账户, 404 未知的库, 409 名称冲突,
413 身体太大。
审计跟踪
每次创建、删除、注册、登录、注销、推送和拒绝读取都是
记录在 users.db 包含时间、参与者、存储库、状态代码、IP和详细信息。
管理员可以阅读。密码和令牌永远不会写入审计
,并且只有它们的哈希值存储在数据库中。
settings.json
一开始就创造;在服务器上编辑它,它没有HTTP端点。
运行 microgit-server --settings (或 -s)作为交互式终端编辑器,
或者直接编辑文件。
| 关键 | 默认的 | 意义 |
|---|---|---|
host | "127.0.0.1" | 绑定地址(环回保持私有) |
brand | "litegit" | 页眉、HTML标题和页脚中的名称 |
tagline | "" | 字后品牌在页眉;空只显示品牌 |
port | 3000 | 要侦听的TCP端口 |
reposDir | "repos" | 裸存储库存储在哪里 |
dataDir | "data" | SQLite文件存储在哪里 |
publicUrl | "" | 在克隆url和生成的链接中使用完整的来源;空=从请求派生 |
domain | "" | 在UI中显示的公共领域,而不是IP; git.example.com 或 https://git.example.com |
trustProxy | false | 阅读 X-Forwarded-Proto/Host/For 从反向代理 |
motd | "" | 签到后显示的横幅;空=无 |
allowRegistration | true | 允许 POST /api/register |
template | "" | 复制到每个新存储库中的文件夹 |
sessionDays | 7 | API会话生存期 |
maxPushBytes | 0 | 一个推包的最大尺寸(0 =无限) |
cacheTtlMs | 5000 | 内存查找缓存TTL |
host, port, reposDir, dataDir, publicUrl 和 domain 读取 一次
在启动时,因此在更改它们(特别是数据目录)后重新启动
数据库打开时不能移动)。 motd, template, brand,
tagline, allowRegistration, sessionDays, maxPushBytes 和 cacheTtlMs
每个请求读取并立即应用。
使用域而不是IP
集 domain 当通过主机名(即克隆按钮)到达服务器时,
copy字段,链接和API响应显示域而不是任何地址
请求到达的时间是:
{
"domain": "git.example.com"
}
假设裸主机是HTTP;当服务器是时显式地编写方案 TLS后面:
{
"domain": "https://git.example.com"
}
公共起源的优先级是 PUBLIC_URL (环境)→ publicUrl →
domain →请求 Host 头。也就是说你只需要一个
publicUrl 或 domain;如果 publicUrl 已经设置好了,它就赢了。重新启动
更改任何一个后的服务器。
环境变量(覆盖)
以上一切都属于 settings.json. 环境只是凌驾于它之上,
这是方便的容器和一次性运行:
| 变量 | 默认的 | 意义 |
|---|---|---|
PORT, HOST | 3000, 127.0.0.1 | 听地址 |
GIT_REPOS_DIR | repos | 裸存储库存储在哪里 |
GIT_DATA_DIR | data | SQLite文件存储在哪里 |
GIT_SETTINGS_FILE | settings.json | 设置文件路径 |
PUBLIC_URL | 空 | 在克隆url中使用的来源;赢了 domain |
TRUST_PROXY | 0 | 阅读 X-Forwarded-Proto/Host/For 从反向代理 |
故障排除
Authentication failed在推 —使用帐户的用户名/密码,而不是a 令牌。401登录后使用脚本 -传递会话cookie或承载令牌; 卷曲不保持sid调用之间的Cookie本身。- 找不到存储库 - owner和name后面区分大小写 归一化;检查清单端点。
- 已使用的端口 ——设置
PORT或改变port在settings.json。
npm包
服务器被发布为 microgit-server NPM包(参见 安装 以上为
安装命令)。安装完成后 microgit-server 二进制文件可用:
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
这个 --settings Flag打开一个终端菜单进行编辑 settings.json选一个
按号码设置,输入新的数值,或按 h 获取描述的帮助屏幕
每一个选择。新闻 0 要保存并退出, q 抛弃。
配套的命令行客户端是 单独的 包:
npm install -g microgit-cli。