# my-gitlab **Repository Path**: e4glet/my-gitlab ## Basic Information - **Project Name**: my-gitlab - **Description**: 个人使用的git仓库管理平台,自建服务器进行git项目管理 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-17 - **Last Updated**: 2026-09-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # My GitLab · 个人 Git 仓库服务 单用户、无注册,用最少的代码实现安全的 Git Smart HTTP 个人仓库服务。 ## 项目展示 | 首页仓库列表 | 仓库详情 | 访问令牌 | |---|---|---| | ![仓库列表](docs/screenshot-list.png) | ![仓库详情](docs/screenshot-detail.png) | ![访问令牌](docs/screenshot-tokens.png) | ## 技术栈 - 后端:Node.js + Fastify + TypeScript + SQLite(better-sqlite3) - 前端:React + Vite + Tailwind CSS - Git 底层:直接调用系统 `git`(`upload-pack` / `receive-pack --stateless-rpc`) - 部署:Docker + Nginx(可选) ## 目录结构 ``` my-gitlab/ ├── backend/ # Fastify 服务(Web API + Git Smart HTTP) │ └── src/ │ ├── index.ts │ ├── config.ts # 环境变量(JWT_SECRET 弱值拒绝启动) │ ├── db.ts # SQLite + 轻量迁移 │ ├── auth.ts # Basic 鉴权 + JWT 会话版本校验 │ ├── seed-admin.ts # 环境变量种子单用户 │ ├── routes/ # auth(登录/改密)/ repos / tokens / files(浏览) │ ├── git/ # Smart HTTP(clone/pull/push) │ └── utils/ # repoPath / auth-helpers / pat-crypto / language ├── frontend/ # React 页面:登录 / 首页列表 / 新建 / 详情(代码+设置)/ 设置(密码+令牌) ├── data/ # SQLite + 裸仓库(gitignored,不进仓库) ├── agents.md # 开发记忆(改代码前先读) ├── LICENSE # MIT ├── Dockerfile ├── docker-compose.yml └── nginx.conf.example ``` ## 认证设计(单用户、无注册) - 单用户账号由环境变量 `ADMIN_USER` / `ADMIN_PASS` 在首次启动时自动创建。 - **首页与公开仓库免登录**:任何人可看公开库列表、代码、README 并匿名 clone;私库对匿名统一 404。 - **登录后管理**:新建/改/删仓库、令牌、改密码等写操作一律要登录。 - 首次登录用的是默认密码,登录后顶部会有常驻提醒,直到去「设置」页修改密码。 - Web 登录签发 JWT(带会话版本),前端存 localStorage;改密码会让所有已签发 JWT 立刻失效,需重登。 - 改密码接口:`PATCH /api/me/password`(需旧密码,新密码至少 8 位)。 - 登录限流:同 IP 10 分钟内失败 10 次后返回 429。 - Git 操作用 HTTP Basic Auth:用户名 + **PAT**(密码也兼容登录密码,建议用 PAT)。 - PAT 明文加密存库(密钥为服务端 `JWT_SECRET`,不进数据库),登录后可在「设置」页随时重新查看/复制。 - 仓库详情页可选令牌,一键复制「带令牌的 Clone / 关联远程命令」,不用再手拼地址。 - 仓库详情页带文件浏览:分支切换、目录面包屑、文件预览(1MB 以内文本),当前目录的 README.md 自动渲染(含相对路径配图)。 - 公开仓库允许匿名 clone;push 一律需要认证。 - 公开库可分享:详情页复制「公开访问页地址」(`/repo/:name`,首页本就公开),对方免登录即可看文件、README 并一键复制 clone 命令;匿名访问私库统一 404,不泄露存在性。 ## 本地开发 ```bash # 1) 后端 cd backend cp .env.example .env # 必须改 JWT_SECRET(≥16 位随机串,定下别换);顺手改 ADMIN_PASS npm install npm run dev # http://127.0.0.1:3000 # 2) 前端(另开终端) cd frontend npm install npm run dev # http://127.0.0.1:5173(/api 与 *.git 已代理到后端,首页认准 5173) ``` 默认管理员:按 `.env` 里的 `ADMIN_USER` / `ADMIN_PASS` 登录(示例为 admin / change-me, 首次登录后请立即去「设置」页修改密码,顶部的修改密码提醒会一直保留到改掉为止)。 ## 使用流程 1. 登录 → 新建仓库:填名称(路径自动生成,可手改)、介绍,选开源/私有, 可勾选「初始化仓库」自动生成 README.md(+ 可选 .gitignore 模板),建完直接有文件列表。 2. 到「设置 → 访问令牌」页生成 PAT(登录后可随时重新查看/复制,不用一次拷走)。 3. 仓库详情「代码」页选令牌,一键复制 Clone / 关联远程命令,本地执行: ```bash git clone http://<用户名>:@:3000/hello.git cd hello # ... 写代码 ... git push origin main ``` 公开仓库无需令牌:`git clone http://:3000/hello.git` 即可, 详情页也有「复制匿名 Clone」和免登录的公开访问页地址,直接发给别人就行。 > 开发模式下前端 dev server(默认 5173)已配置代理,`*.git` 请求会转发到后端, > 所以页面上显示的同源 clone 地址(5173)在开发时同样可用;生产环境前后端同端口,无此区别。 > 注意:改了 `frontend/vite.config.ts` 后要重启 `npm run dev` 才生效。 ## 生产部署(Docker) 单容器单端口(3000),Web + API + Git 一起上,数据落 `/data` 卷。 ```bash JWT_SECRET=至少16位随机串 ADMIN_PASS=你的密码 docker compose up -d --build ``` `JWT_SECRET` 不设或太弱会拒绝启动,定下后别再换。**完整步骤(含备份/升级/Nginx HTTPS/排错)见 [Docker 部署指南](docs/docker-deploy.md)**。 ## 安全要点 - 无注册路由,只有登录;登录同 IP 10 分钟失败 10 次后 429。 - 单用户约束:库里已有异名账号时不再自动建第二个,只告警。 - `JWT_SECRET` 缺失/弱值直接拒绝启动;密码 bcrypt 哈希。 - 改密码会让所有已签发 JWT 立刻失效(会话版本),前端自动退到登录页。 - PAT 双存:`sha256` 哈希(Git 鉴权)+ AES 加密(页面重看,密钥由 `JWT_SECRET` 派生,不进库)。 - 仓库名白名单 `^[a-zA-Z0-9._-]{1,100}$`,路径强制约束在 `REPO_ROOT` 内,防路径穿越。 - Git 子进程用 `spawn('git', [...固定参数, 绝对路径])`,不拼 shell,防注入;`ref` 禁 `-` 开头。 - 私有仓库读/写都要认证(匿名 404);公开仓库只有 push 要认证。 - CORS 默认只放行本地 5173(`CORS_ORIGIN` 可配);生产单端口同源不受影响。 ## 开源协议 本项目采用 [MIT License](LICENSE) 开源,版权归 e4glet 所有,欢迎 fork 和 PR。