资讯动态

内网自建Git服务器:Gitea轻量部署、权限管理与备份实践

发布时间:2026/10/23 1:25:57 来源:尧图企业网站定制
在内网搭一个 Git 私有服务器是很多开发团队迟早要面对的事。一开始代码可能零散放在个人磁盘里几个人靠压缩包传来传去等到项目变多、成员变多才发现分支管理、权限控制、历史追溯全都是一团乱麻。Gitea 正是解决这个问题的轻量级方案——一个用 Go 写的 Git 托管服务几十兆的二进制文件就能跑起来装好后团队就能通过浏览器管理仓库、审查代码、跟踪 Issue相当于在局域网里自建了一个轻量版 GitHub。这篇文章适合所有想在内网搭代码仓库的人刚接触 Git 服务运维的新手可以照着一步步操作已经被 GitLab 的庞大资源消耗折腾过、想换轻量方案的开发者也能找到合适的迁移思路。我过去几年在不同环境里部署过好几套 Git 服务从裸 Git 仓库到 Gitea 都试过这篇文章会把部署流程、关键配置、权限模型和踩过的坑一次讲透让你少走弯路。1. 为什么需要自建 Git 服务器需求分析与方案选型1.1 什么场景真正需要私有 Git 服务先说实话不是所有人都需要自建 Git 服务器。如果只是一个人写代码GitHub、Gitee 这类公有平台的私有仓库完全够用。但当出现下面几种情况时你就该认真考虑在内网搭一套自己的服务了代码敏感或合规要求高某些公司内部项目、实验室课题、外包交付代码不允许上传到外部平台必须存放在自己可控的服务器上。网络条件受限内网开发环境与公网隔离开发者无法顺畅访问外部 Git 平台推送几十 MB 的分支可能要等半天。多人协作需要统一入口团队从共享文件夹 压缩包切换到 Git 工作流需要一个所有人能访问的统一服务器而不是某台开发机上的临时目录。需要离线可用现场开发、应急演练、内网演示环境没有外网但依然要完整的版本管理能力。在这些场景下自建 Git 服务器的价值在于代码永远留在自己的机器上、访问速度不受公网波动影响、权限和备份策略完全由自己掌控。这不是替代 GitHub而是在代码不能出内网的前提下把 GitHub 的那套核心体验搬回本地。1.2 Gitea 对比 GitLab、Gogs 和裸 Git 服务确定要自建之后选型是第一步。我在这一环节对比过四个主流方案Idea 上直接跑裸 Git 仓库加 Gitolite、老牌的 GitLab、Gogs 以及它的继任者 Gitea。直接给结论小团队和一般内网场景Gitea 是性价比最高的选择。方案资源占用部署复杂度功能完整度维护活跃度适合场景裸 Git Gitolite极低较高仅 Git 托管一般极客个人、最小化需求Gogs低低基础功能较低早期轻量场景已不推荐新用Gitea低1GB 内存可跑极低单二进制高Issue/PR/CI 对接/ Wiki活跃中小团队、内网私有部署GitLab高官方建议 4GB 起步高组件多极高完整 DevOps活跃中大型团队、需要完整 CI/CD 平台选 Gitea 而不是 GitLab最核心的原因是资源占用与维护成本。我在一台 1 核 1GB 内存的虚拟机上跑过 Gitea日常内存占用在 200MB 左右一套 GitLab 在同一台机器上几乎跑不起来。而选 Gitea 而不是 Gogs则是因为 Gitea 社区更活跃、Bug 修复更快、插件生态更丰富。如果你只需要能 Git clone/push 浏览器看代码 权限管理Gitea 就是那个刚刚好的工具。1.3 部署方式选型二进制、Docker 还是系统包Gitea 官方提供了三种主流安装路径二进制包、Docker 镜像、Linux 系统包apt/yum。我的建议是单机 CentOS/Debian 服务器优先用官方二进制下载后一个文件就是整个服务升级时替换文件即可依赖最少、排查问题最直观。喜欢容器化、机器上已有 Docker 环境优先用 Docker Compose配置清晰、数据目录独立、迁移方便。需要自动化装机可以用系统包配合配置管理工具但我个人不喜欢系统包方式因为 Gitea 迭代快系统源里的版本往往滞后。下面两套部署方式我分别给出完整步骤大家按自己的环境选一套执行就行。2. 环境准备与安装部署全流程2.1 硬件与系统要求先泼一盆冷水Gitea 虽然轻但不是随便一台机器就能稳定跑。根据我的实战经验给出一份比较稳妥的最低配置参考CPU1 核即可2 核体验更好并发 clone/push 时不会卡顿内存512MB 能跑1GB 建议值团队超过 20 人建议 2GB磁盘按仓库大小估算建议至少预留仓库总容量 × 1.5的空间另留系统盘余量系统Linux 为主官方支持 Windows/macOS 但生产场景几乎都是 Linux我这里以 Debian/Ubuntu 和 CentOS 为例提示很多人忽略磁盘 IO 对 Git 服务的影響。Git 操作是大量小文件的随机读写机械硬盘上 clone 大仓库会明显感觉慢有条件尽量用 SSD哪怕是做个 RAID1 的机械盘也会好很多。2.2 二进制安装步骤详解二进制安装是零依赖路线特别适合最小化系统。步骤分四步准备系统用户和目录、下载二进制、初始化服务、配置系统服务。第一步创建专用用户和目录。Git 服务不建议直接用 root 跑权限太大会成为安全隐患也不利于后面做备份和权限管理# 创建 gitea 系统用户家目录设为 /var/lib/gitea sudo adduser --system --home /var/lib/gitea --group gitea # 创建标准目录结构 sudo mkdir -p /var/lib/gitea/{custom,data,log} sudo chown -R gitea:gitea /var/lib/gitea第二步下载二进制文件。到 Gitea 官方下载页找到对应平台的二进制包这里以 Linux amd64 为例# 注意版本号请到官网查最新稳定版不要用太旧的版本 sudo wget -O /tmp/gitea https://dl.gitea.com/gitea/1.22.1/gitea-1.22.1-linux-amd64 sudo install -o gitea -g gitea -m 0755 /tmp/gitea /usr/local/bin/gitea第三步先手动启动一次做首次初始化。这一步不要急着注册系统服务先用前台模式确认能跑起来方便直接看日志排错GITEA_WORK_DIR/var/lib/gitea sudo -u gitea /usr/local/bin/gitea web -p 3000看到类似Listen: http://0.0.0.0:3000的日志说明服务启动成功。CtrlC 停掉进入第四步配置系统服务让它在开机后自动运行。以 systemd 为例sudo tee /etc/systemd/system/gitea.service EOF [Unit] DescriptionGitea (Git with a cup of tea) Afternetwork.target Requiresnetwork.target [Service] Usergitea Groupgitea WorkingDirectory/var/lib/gitea EnvironmentGITEA_WORK_DIR/var/lib/gitea ExecStart/usr/local/bin/gitea web -p 3000 Restartalways RestartSec2 [Install] WantedBymulti-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now gitea到这里Gitea 服务已经在 3000 端口跑起来了。访问http://服务器IP:3000就能看到安装引导页。需要注意的是如果你改了 SSH 默认端口后面会讲systemd 的 ExecStart 里也可以追加--ssh-port 2222参数让 Gitea 的 SSH 服务绑定到指定端口。2.3 Docker Compose 部署方式已经在用 Docker 的环境用 Compose 管理 Gitea 会更省心。数据目录通过挂载卷持久化升级就是拉新镜像重新 create不需要关心二进制版本。我实际使用的 Compose 配置如下version: 3 services: gitea: image: gitea/gitea:1.22.1 container_name: gitea environment: - USER_UID1000 - USER_GID1000 - GITEA__serverSSH_PORT2222 - GITEA__serverDOMAIN192.168.1.100 - GITEA__serverROOT_URLhttp://192.168.1.100:3000/ restart: always volumes: - ./gitea:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro ports: - 3000:3000 - 2222:2222用 Docker 部署有三个必须留意的点权限一致性容器内的USER_UID1000要和宿主机上挂载目录属主的 UID 一致否则容器写./gitea目录会出现 Permission denied。SSH 端口映射宿主机 2222 映射到容器 22后面的GITEA__serverSSH_PORT2222是告诉 Gitea外部用户要用 2222 端口连 SSH这个必须和端口映射对上否则克隆地址会出错。ROOT_URL 要写对如果客户端是通过 IP 访问就写http://IP:3000/如果将来有域名最好一开始就规划好因为后期改 ROOT_URL 会影响仓库的克隆地址显示老用户可能困惑。启动命令就一行docker compose up -d这套配置里所有数据都在宿主机./gitea目录下备份时整个目录拷走即可。相比二进制方式Docker 的维护确实更省心代价是多了一层容器网络的概念新手排错时要多考虑端口映射问题。3. 初始化配置与核心功能落地3.1 首次访问、管理员账号与数据库选择浏览器打开 Gitea 页面会进入安装配置界面。这里有几个关键选项直接决定后续使用体验我逐一说明。数据库选择是第一个选择题。Gitea 支持 SQLite、MySQL、PostgreSQL 三种。我的经验是团队 10 人以下、仓库量不大直接选 SQLite零额外依赖一个文件搞定备份也简单。团队较大、准备认真运维选 MySQL 或 PostgreSQL并发写入和可靠性更好前提是你对数据库本身有维护能力。我见过不少人在这里犹豫半天其实没必要。Gitea 官方对 SQLite 的支持足够成熟中小团队完全不需要为一个代码托管工具单独维护一套数据库。如果以后真需要迁移到 MySQLGitea 后台也有迁移工具可以操作但麻烦程度不低所以一开始想清楚就行。管理员账号在安装页面上可以直接创建。这里提醒一点管理员账号不要用团队公共名称如 admin/root 这种建议用个人真实用户名方便审计操作记录。服务域名与基础 URL这两个字段决定了仓库的 HTTPS/SSH 克隆地址怎么生成。内网环境直接填服务器 IP例如http://192.168.1.100:3000/。如果服务器后面要接域名建议在安装时就规划好减少后期调整的连锁影响。3.2 SSH 访问与 HTTPS 证书配置Gitea 的 Web 端可以做很多操作但团队日常使用 Git 命令行时SSH 通道是主要入口。默认 Gitea 会尝试绑定 22 端口问题是很多服务器上 22 已经被系统 SSH 服务占用了。解决方案就是给 Gitea 指定一个独立端口比如 2222然后在每个用户的克隆地址里体现。端口绑定设置位于配置文件app.ini的[server]节[server] SSH_PORT 2222 SSH_LISTEN_PORT 2222改完后重启 Gitea再进入用户后台添加 SSH 公钥# 在客户端生成密钥如果还没有 ssh-keygen -t ed25519 -C 你的备注 # 查看公钥内容 cat ~/.ssh/id_ed25519.pub把公钥粘贴到设置 - SSH 密钥里保存。之后客户端要配置一个 config 片段避免每次指定端口# 修改 ~/.ssh/config Host gitlab-internal HostName 192.168.1.100 Port 2222 User git IdentityFile ~/.ssh/id_ed25519这样就可以用git clone gitgitlab-internal:用户名/仓库名.git来克隆命令简洁不少。关于 HTTPS 证书内网环境一般没有可信 CA 签发的证书两种选择一是自己生成自签名证书并在客户端系统里安装信任二是直接用 HTTP 加上内网访问边界控制。我建议小团队在纯内网里先用 HTTP把精力聚焦在核心功能上等有公网访问需求时再通过反向代理统一加 HTTPS。注意Gitea 对 SSH 协议的支持是完备的但前提是服务器上要装了 Git。CentOS 系机器用yum install git -yDebian 系用apt install git -y装完确认git --version有输出否则 SSH 通道会报 fatal: repository not found 但问题根本不在权限。3.3 用户、组织与仓库权限设置内网 Git 服务的权限模型是团队协作中最容易混乱的部分。Gitea 的权限体系分三层用户、组织、仓库理解这三层能避免很多为什么我看不到那个仓库的问题。用户层面管理员可以在后台创建用户也可以开放注册。内网环境建议关闭自动注册由管理员统一创建账号这样能避免不是团队的人混进来。组织层面当项目不止一个时建议建组织。比如公司有前台组和后台组就分别建两个组织然后在组织里建仓库。组织的好处是权限可以批量管理——成员一进组自动获得组内所有仓库的对应权限不用逐个仓库添加人。仓库权限Gitea 支持读、写、管理三级权限。我给个实用建议核心分支main/master默认只给少数人管理权限其他人通过 Pull Request 提代码。这样做一开始会有点麻烦但能有效防止有人在主分支上直接乱搞、或把自己的半成品推到主干。管理员在后台站点管理 - 用户 - 编辑里可以为每个用户调整权限组织管理页也可以设置成员角色。实际运维中我习惯把权限控制写进一份团队文档里谁在哪个项目什么角色一目了然新成员加入时照着文档开权限就行不用每次口头交代。3.4 关键配置文件 app.ini 解读Gitea 的配置文件是app.ini二进制安装时通常放在/var/lib/gitea/custom/conf/app.iniDocker 安装在容器内/data/gitea/conf/app.ini。虽然 Web 后台能配置大部分内容但有些关键参数只有改配置文件才生效。我把常用的几个节列出来[server] PROTOCOL http DOMAIN 192.168.1.100 ROOT_URL http://192.168.1.100:3000/ HTTP_PORT 3000 SSH_PORT 2222 SSH_LISTEN_PORT 2222 LFS_START_SERVER true [database] DB_TYPE sqlite3 PATH /var/lib/gitea/data/gitea.db [repository] DEFAULT_PRIVATE private MAX_CREATION_LIMIT 0 DEFAULT_BRANCH main [ui] EXPLORE_PAGESIZE 20 [service] DISABLE_REGISTRATION true REQUIRE_SIGNIN_VIEW true [mailer] ENABLED false [openid] ENABLE_OPENID_SIGNIN false几个参数说明一下LFS_START_SERVER true开启 Git LFS 支持。如果团队仓库里要放设计稿、二进制包这类大文件这个必须开否则仓库会越来越臃肿。DISABLE_REGISTRATION true禁止自助注册配合管理员统一建号。REQUIRE_SIGNIN_VIEW true未登录用户不能查看任何内容这是内网私有仓库的基本要求。DEFAULT_PRIVATE private默认新仓库是私有避免有人误建公开仓库后代码泄露。每次改完app.ini记得重启 Gitea 让配置生效systemctl restart gitea或docker restart gitea。4. 进阶玩法Webhook、备份迁移与日常维护4.1 Webhook 对接 CI/CD 和消息通知Gitea 虽然内置了简单的 CIGitea Actions但很多团队在初期会用它和已有的 CI 系统对接。这时候 Webhook 是主角。Webhook 的配置入口在仓库设置 - Web 钩子可以设置推送后触发、创建分支后触发、Issue 变动后触发等事件。一个典型的用法是每次推送到 main 分支后Gitea 向 CI 系统发送一个 POST 请求CI 收到后自动拉取代码、执行测试、构建产物。配置时要注意两点Webhook 的 URL 必须是 CI 系统可达的地址内网环境直接写http://CI服务器IP/trigger即可。密钥Secret要配对好CI 端要校验签名防止内网中有人伪造请求触发构建。我在实际使用中还让 Gitea 的 Webhook 对接过企业微信群机器人推送代码后自动发一条消息带上提交者、提交信息和 commit 链接团队的代码动态一目了然。这个操作在仓库设置 - Web 钩子 - 添加 Webhook里选择类型为企业微信/Gitee/自定义均可自定义的话把机器人 Webhook 地址填进去消息格式按对应文档写一个 JSON 模板就行。4.2 数据备份与恢复搭好服务之后备份可能是最容易被忽略、一旦出事最痛的事。Git 仓库本身有分布式特性每台开发机上都有全量副本但 Gitea 的数据库里还有 Issue、评论、用户信息、Webhook 配置这些丢了很难恢复。我的备份方案是三部分一起备份数据库文件SQLite 的话直接拷贝/var/lib/gitea/data/gitea.dbMySQL 用mysqldump。仓库裸目录默认在/var/lib/gitea/data/repositories这里面是所有仓库的 git 数据。配置文件app.ini、以及 LFS 对象目录data/lfs。最简单的备份脚本骨架#!/bin/bash BACKUP_DIR/backup/gitea_$(date %Y%m%d) mkdir -p $BACKUP_DIR # 停服务避免写数据可选高频场景可用文件系统快照代替 systemctl stop gitea cp -r /var/lib/gitea/data $BACKUP_DIR/data cp /var/lib/gitea/custom/conf/app.ini $BACKUP_DIR/app.ini systemctl start gitea # 只保留最近 7 天备份 find /backup -name gitea_* -mtime 7 -exec rm -rf {} \;关于备份频率团队活跃的话建议每天一次全量备份。Git 仓库体积通常不大几个 GB 都算多了一天一次完全扛得住。恢复的时候把数据库文件和 repositories 目录放回原位置改好属主、起服务即可。这一步一定要在干净环境里提前演练一次我见过太多以为备份了恢复时才发现问题的情况。4.3 日常维护与升级Gitea 的升级路径非常平滑下载新版二进制、替换旧文件、重启服务Gitea 会自动迁移数据库结构。用 Docker 就更简单拉新镜像重启容器。但升级前有一条铁律先备份再升级。Gitea 几乎每个版本都有数据库结构变更万一你跳过了几个大版本迁移脚本可能兼容不上。日常维护我还有几个习惯每周看一眼磁盘用量仓库增长速度超预期时及时排查是谁在推大文件。定期清理超过一年的临时分支和合并后的分支避免仓库列表堆积。关注 Gitea 官方公告遇到安全更新尽快升级。内网不代表绝对安全尤其是服务器还能被部分外部人员访问时。5. 常见问题排查与避坑实录5.1 SSH 连不上的几种典型原因SSH 问题占了我排障记录的半数以上而且原因通常很隐蔽。我整理了几个高频场景场景一Permission denied (publickey)这个提示最直接的原因是公钥没配对或没生效。按顺序排查确认你用的密钥是否已添加到 Gitea 个人设置里注意区分是添加到用户还是仓库权限不对也一样拒绝。确认客户端用的是 ed25519 或 RSA 类型老一点的系统默认生成 RSA但密钥没加入 ssh-agent 也会拒绝。在 Gitea 后端执行su - gitea -s /bin/bash后手动 clone 一次如果服务端本地能通问题基本在客户端特定配置上。场景二fatal: could not read Username for http://...这是走 HTTP 协议时没带用户名密码。解决办法一是用 SSH 协议替代二是在.git/config里补全带凭据的 URL或者用凭据管理器缓存密码。内网环境为了安全我还是推荐 SSH。场景三换端口后人人都 clone 失败如果你把 SSH 端口从 22 改成 2222但 Web 端的克隆地址没更新用户复制的命令就会连错端口。改完SSH_PORT后确认站点管理里的本服务信息页显示的新端口再让团队重新复制克隆地址。5.2 端口、防火墙与反向代理问题内网部署最容易被防火墙挡掉。装完 Gitea 后发现浏览器打不开页面十有八九是系统防火墙没有放行端口# CentOS/RHEL 系 sudo firewall-cmd --permanent --add-port3000/tcp sudo firewall-cmd --permanent --add-port2222/tcp sudo firewall-cmd --reload # Debian/Ubuntu 系 sudo ufw allow 3000/tcp sudo ufw allow 2222/tcp如果 Gitea 前面还挂了 Nginx 反向代理要特别注意ROOT_URL里写的协议。Nginx 上终止 HTTPS 时ROOT_URL应该写https://域名/而不是http://IP:3000/否则 Web 端生成的资源链接会指向错误的协议和端口页面能打开但样式全丢、克隆地址不对。我当时第一次接 Nginx 时就踩了这个坑排查了半小时才发现是 URL 生成逻辑问题而不是 Nginx 配置错误。5.3 数据库与存储优化经验SQLite 模式用久了一个明显的优化点是定期执行VACUUM回收磁盘空间尤其是频繁删建仓库后。Gitea 自带的gitea doctor命令是个宝藏可以检查数据库健康、修复仓库记录问题、清理孤儿数据sudo -u gitea GITEA_WORK_DIR/var/lib/gitea /usr/local/bin/gitea doctor check另外仓库目录里.git对象文件如果过于分散可以执行git gc来压缩对象。对长期活跃的仓库建议设定 Gitea 后台的 GC 策略。我自己会在每周日凌晨跑一个脚本对近期有提交的仓库执行git gc --aggressive --prunenow能显著降低仓库体积和 clone 时间。5.4 一些容易被忽略的小细节最后分享几个我在真实运维中碰到的小问题单个看着不起眼但加起来很影响体验系统时区不对Gitea 的提交时间显示和使用者本地时间不一致排查半天发现服务器时区是 UTC设置成Asia/Shanghai后就正常了。仓库名大小写Git 对仓库路径是大小写敏感的创建仓库时如果习惯了MyProject这种写法克隆地址一定不能写错大小写很多404 仓库不存在其实是路径写错。服务器时钟不同步如果机器没有配置 NTP 时间同步多个开发机之间提交时间会出现错乱合并代码检查历史记录时非常混乱建议内网服务器统一配置时间同步。LFS 但没有配置对象存储LFS 默认把大文件也存在数据目录里备份时如果把 LFS 目录漏了恢复后历史大文件会丢失这个比普通仓库数据丢失还难发现。我在内网跑 Gitea 的这几年最大的体会是这类工具的价值不在于功能多炫而在于稳定、不折腾。只要把上面这些基础配置和备份习惯做好它能在角落里默默跑好几年不用你操心。如果你团队还在用共享文件夹传代码不妨花一个下午把 Gitea 搭起来从第一个仓库成功 clone 的那一刻起你就再也不想回到压缩包时代了。真要说还有什么进阶方向等用熟练了可以考虑把 Gitea Actions 也跑起来把构建、测试都收到内网里那整个开发流就闭环了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑