技术文章 / 排查笔记

企业怎样用 Gitea 搭建私有 Git 仓库?Ubuntu 与 Docker 分步部署教程

在Ubuntu上用Docker Compose搭建Gitea小团队私有Git试点,配置SSH隧道、独立Git端口和持久存储,逐步验证推送、克隆与权限边界。

企业怎样用 Gitea 搭建私有 Git 仓库?Ubuntu 与 Docker 分步部署教程技术文章配图

配置文件、运维脚本散落在个人电脑,交接时很难确定哪份是最新版。可以先用一台独立 Ubuntu 虚拟机部署 Gitea,把一个不含敏感信息的试点仓库纳入版本管理。先验收持久存储、SSH 推送和权限拒绝,再考虑接入正式项目。

本文采用 Gitea 28.3.0 的普通 Docker 镜像、SQLite 与单实例。Web 页面只绑定服务器回环地址,管理员通过 SSH 隧道访问;Git SSH 使用内网的 2222 端口。它是一套小团队试点方案,不包含高可用、公网开放或现有仓库迁移。安装步骤按官方文档整理,命令为操作示例,需在你的隔离环境逐步验证。

先分清三个地址,避免网页能开却克隆失败

Gitea 是自托管 Git 服务,负责保存仓库及其协作记录;Git 则在客户端记录提交并推送。容器可以重建,但持久目录必须保留。

管理员隧道、Git SSH 与持久数据的分离关系

图中区分 Web 管理、Git 传输和磁盘持久化;它说明本例连接关系,不代表已经完成部署。

用途 本例参数 检查重点
服务器内网地址 192.168.50.20 替换成专用试点机地址,不占用现有服务
宿主机管理员 SSH 22 使用已有管理账号与已核验主机指纹
Web 后端 服务器 127.0.0.1:3000 不直接开放内网 HTTP 登录
Git SSH 192.168.50.20:2222 → 容器22 与宿主机管理 SSH 分开
持久目录 宿主机 /srv/gitea-pilot/data → 容器 /data 容器删除后仍保留

网页入口使用本地隧道,所以 ROOT_URL 指向访问者自己的回环地址;SSH_DOMAIN 则指向服务器内网地址。SSH_PORT 用于生成克隆地址,不意味着要把容器 OpenSSH 改到2222。配置含义见 Gitea 配置参考。

第一步:确认试点环境,而不是直接安装到生产服务器

准备一台 Ubuntu 24.04 LTS 专用虚拟机,建议从2核、2GB内存、20GB可用磁盘起步。这是本文的试点预算,不是官方容量保证;仓库体积、并发和索引会改变需求。已有虚拟化平台可先参考虚拟机隔离恢复思路,明确服务负责人和恢复位置。

前置条件是已按 Docker 官方 Ubuntu 安装说明安装受支持的 Docker Engine 和 Compose 插件;客户端具备 Git 与 OpenSSH。不要为了本文替换已有 Docker、关闭其他容器或调整全局防火墙。

在服务器执行以下只读检查:

docker version
docker compose version
ip -br address
sudo ss -lntp
df -h /srv

确认192.168.50.20确实属于这台机器、3000和2222未被占用,且你能正常使用宿主机22端口登录。遇到地址不符、端口占用、存储不足或其他业务依赖时停止,先重新分配环境。Docker 发布端口有自己的网络规则,不能仅凭 UFW 规则判断已隔离;参见 Docker 端口发布说明。

第二步:建立单独的数据目录和 Compose 文件

以下操作只针对新试点目录。若目录已经存在并含文件,不覆盖,先核对是否属于旧实例。

sudo install -d -m 0750 -o "$USER" -g "$(id -gn)" /srv/gitea-pilot
cd /srv/gitea-pilot
sudo install -d -m 0750 -o 1000 -g 1000 data
nano compose.yaml

将下列内容保存到文件。镜像固定为2026年11月9日核对到的正式版本28.3.0;以后升级应先阅读对应发行说明并另做测试,不使用会漂移的 latest 标签。

name: gitea-pilot
services:
  gitea:
    image: docker.gitea.com/gitea:28.3.0
    restart: unless-stopped
    environment:
      USER_UID: "1000"
      USER_GID: "1000"
      GITEA__database__DB_TYPE: sqlite3
      GITEA__server__DOMAIN: "127.0.0.1"
      GITEA__server__ROOT_URL: "http://127.0.0.1:3000/"
      GITEA__server__SSH_DOMAIN: "192.168.50.20"
      GITEA__server__SSH_PORT: "2222"
      GITEA__service__DISABLE_REGISTRATION: "true"
      GITEA__service__REQUIRE_SIGNIN_VIEW: "true"
    volumes:
      - ./data:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "127.0.0.1:3000:3000"
      - "192.168.50.20:2222:22"

SQLite 将数据库保存在实例数据范围内,适合这次单机试点;不要把它当成多实例共享数据库。选择普通镜像后,也不能直接换成 rootless 镜像继续挂载旧目录。基础挂载和镜像区别见 Gitea Docker 安装文档。

Intel NUC6 的内存与存储内部实拍

实拍来源:Laserlicht,Intel NUC6 inside,CC BY-SA 4.0,图片经缩放转码,非本文现场。照片用于说明持久数据仍依赖实际存储,不是指定硬件推荐,也不证明该设备运行过本例。容器重建不会替你增加磁盘空间或形成备份。

第三步:启动后先看映射与日志

在服务器的试点目录执行:

docker compose config --quiet
docker compose pull
docker compose up -d
docker compose ps
docker compose logs --tail=80 gitea

第一条只解析配置,成功不代表容器运行或业务正常。后续检查服务是否保持运行、Web是否映射到回环地址、Git是否映射到指定内网地址。不要把整段日志上传公开工单;本地排障时也应先遮蔽账号、路径与内部地址。

若日志报目录写入失败,核对数据目录的数字UID/GID与1000一致;不要使用全局777权限。若报端口已占用,不杀现有进程。若容器重启循环,先保存错误并停止这一个试点服务,不能以反复重建代替诊断。

第四步:通过加密隧道完成首次安装

在你的工作站另开终端,将示例管理员账号替换为已有宿主机账号。先独立核验服务器SSH主机指纹,再连接,不关闭主机密钥检查。

ssh -N -o ExitOnForwardFailure=yes -L 127.0.0.1:3000:127.0.0.1:3000 admin@192.168.50.20

保持终端运行,在工作站浏览器打开以下地址:

http://127.0.0.1:3000/

HTTP仅存在于工作站本地和服务器回环段,跨网络的Web流量由管理SSH隧道承载。不得把端口绑定改为所有地址,再用明文HTTP输入真实密码。工作站3000被占用时,不强行关闭别人的应用;先为整个试点统一规划新端口和ROOT_URL。

首次安装页核对SQLite3、站点URL、SSH域名和SSH端口。展开管理员设置,明确创建专用管理员,使用密码管理器生成唯一密码;不要依赖公开注册来抢建第一个账号。安装完成后登录“站点管理 → 用户账号”,创建普通试点用户pilot-writer和pilot-reader,各自设置独立密码;页面名称可能随语言包略有差异。

退出后确认没有可用的自助注册入口。每名需要Web操作的试点用户,都要使用经授权的宿主机账号建立自己的隧道;无法接受这一方式时,应先部署可信HTTPS反向代理,再接入团队。正式URL改变后同步修改ROOT_URL并重新验证克隆链接;参见 Gitea HTTPS配置。

第五步:用普通账号创建私有仓库和SSH密钥

用pilot-writer登录,在“新建仓库”中创建netops-pilot,勾选私有并初始化README。不要导入现有项目,不放路由器密码、VPN配置、客户资料或生产证书。进入仓库“设置 → 协作者”,加入pilot-reader,仅授予Read。管理员账号不用于日常提交。

在写入者工作站生成单独的测试密钥。下面文件名若已存在,停止并改用另一个新名称,不覆盖旧密钥。按提示设置口令。

ssh-keygen -t ed25519 -f ~/.ssh/gitea_pilot_writer -C "gitea-pilot-writer"
cat ~/.ssh/gitea_pilot_writer.pub

将公钥添加到pilot-writer的“用户设置 → SSH/GPG密钥”。只复制.pub文件内容;私钥始终留在工作站。通过可信管理通道核对容器Git SSH的主机指纹:

cd /srv/gitea-pilot
docker compose exec gitea ssh-keygen -lf /data/ssh/ssh_host_ed25519_key.pub

若该主机密钥文件不存在,停止并检查实际镜像的SSH初始化日志,不能用未知指纹继续。然后在工作站测试2222端口;宿主机登录使用的admin与Git SSH使用的git是两种账号。

ssh -p 2222 -i ~/.ssh/gitea_pilot_writer -o IdentitiesOnly=yes -T git@192.168.50.20

预期是识别对应Gitea用户并提示不提供shell,不是进入服务器命令行。不要只按退出码判断此测试;还需完成下一步真实Git读写。

第六步:验收提交、重新克隆和拒绝权限

下面在写入者工作站的空测试目录执行,仓库属主按实际账号替换。这个SSH URL明确携带2222,不能换成默认22端口的简写。

GIT_SSH_COMMAND='ssh -i ~/.ssh/gitea_pilot_writer -o IdentitiesOnly=yes' git clone ssh://git@192.168.50.20:2222/pilot-writer/netops-pilot.git
cd netops-pilot
git config user.name "Pilot Writer"
git config user.email "pilot-writer@example.invalid"
printf 'Gitea pilot verification\n' > pilot-check.txt
git add pilot-check.txt
git commit -m "Add pilot verification file"
GIT_SSH_COMMAND='ssh -i ~/.ssh/gitea_pilot_writer -o IdentitiesOnly=yes' git push origin HEAD
git rev-parse HEAD

保存提交SHA,回到上级目录克隆到另一个新目录,核对同一SHA和文件内容:

cd ..
GIT_SSH_COMMAND='ssh -i ~/.ssh/gitea_pilot_writer -o IdentitiesOnly=yes' git clone ssh://git@192.168.50.20:2222/pilot-writer/netops-pilot.git netops-pilot-verify
cd netops-pilot-verify
git rev-parse HEAD
cat pilot-check.txt

若目标目录已存在,选择另一个新名称,不覆盖。不要只看网页出现文件名。提交与推送的语义见 Git push文档,SSH端口URL见 Git clone文档。

写入、读取与未授权三种身份的验收关系

验收必须分别使用独立身份;图中的路径表示待执行检查,不是已通过结果。

身份与动作 预期 失败后处理
pilot-writer克隆并推送新提交 允许,重新克隆SHA相同 查密钥所属账号、仓库路径及分支保护
pilot-reader使用自己的密钥克隆 允许,能读同一文件 查协作者Read及密钥是否绑错账号
pilot-reader推送测试分支 拒绝 若成功,立即停止接入并收回多余权限
未加入仓库的第三个普通账号访问 拒绝 查是否误设公开或通过其他团队获得权限
无登录的新浏览器会话访问仓库URL 不能读取私有内容 查仓库可见性与站点登录要求

读者测试要在另一OS账号或独立客户端用自己的密钥操作;不能继续复用写入者密钥或已缓存的认证。Read与Write的区别按 Gitea权限文档核对。页面404有时用于隐藏私有仓库,不能仅凭404断言网络故障。

第七步:确认重建不丢数据,并准备停止方案

只有确认试点没有其他用户正在操作,才在服务器运行以下容器重建检查。它会短暂中断本试点,不在现有业务实例执行。

cd /srv/gitea-pilot
docker compose up -d --force-recreate gitea

随后重新登录,确认账号、仓库、提交SHA仍在,并重新克隆。持久化成功仍不等于备份成功:同盘损坏会同时丢失实例与数据。进入正式使用前,按 Gitea备份与恢复文档制定数据库、仓库、附件与配置的一致性备份,并在隔离位置演练。

不再继续试点时,只停止当前Compose项目;保留文件与数据供复核,不使用删除卷的参数,不清理其他项目。

cd /srv/gitea-pilot
docker compose stop gitea

常见故障怎样缩小范围

网页打不开时,先确认隧道终端仍连接、工作站3000没有被占用,再看服务日志;不要先放开公网。网页正常而SSH超时,检查2222映射、内网路由与上游访问控制;不能把Web成功当成Git端口成功。出现publickey错误,核对公钥绑定的Gitea用户和客户端实际使用的密钥;不要修改宿主机admin账号权限来修复Git用户。写入被拒绝而克隆正常时,查协作者权限与分支保护;不要直接提升为管理员。

任一未授权身份能读取私有内容、服务器主机指纹异常、数据目录意外指向旧业务,均应停止,不继续导入正式代码。

FAQ

内网服务也必须用HTTPS吗?

团队长期使用应部署可信HTTPS。本文通过SSH隧道保护Web跨网络传输,代价是每位使用者都要有经授权的隧道入口;它不替代团队HTTPS方案。

为什么SSH显示2222,却仍映射容器22?

2222是宿主机提供给Git客户端的端口,容器内OpenSSH仍监听22。宿主机管理员22端口是另一条管理路径,两者不能混为一谈。

一个Git克隆能当完整Gitea备份吗?

不能。克隆只覆盖该仓库的Git对象范围,不能替代用户、工单、附件、配置及数据库备份。

SQLite什么时候该换?

本篇仅覆盖单实例小范围试点。并发、体积和可用性要求增长时,先测量瓶颈并规划官方支持的数据库及迁移,不直接让多个实例共用同一SQLite文件。

相关解决方案

需要接入现有虚拟化、网络访问控制或恢复流程时,可先明确主机、地址、责任人与数据边界,再评估煜企企业技术服务。

相关阅读

若需要把试点扩展为团队可用的私有代码服务,可带上人员规模、仓库体积、身份系统与恢复要求,与煜企讨论实施范围。

返回文章列表

相关解决方案

把技术主题连接到可实施的方案

网络设备 & 交换路由

适合从交换机、路由、VLAN、PoE 或网络改造文章进入企业网络设备建设方案。

查看方案 →

VMware服务器虚拟化 – 解决方案

适合从服务器、虚拟机、存储或迁移主题继续进入 VMware 虚拟化架构与实施。

查看方案 →

容灾备份解决方案

适合从备份、误删、勒索、恢复或业务连续性文章进入数据保护方案。

查看方案 →

相关文章

阅读相关内容

返回文章列表