Gitea 自建 Git 服务教程:Docker 部署、仓库迁移与外网安全访问

Gitea 自建 Git 服务封面图

前言

代码放在第三方平台上很省心,但团队里总会遇到几类场景:内网项目不想出公司,家用服务器想留一份私有仓库,旧项目从 GitHub 拉回来做归档,或者只是想有一个轻量的 Git Web 面板。

我自己更喜欢把这类工具先搭成“小而稳”的形态:能创建仓库,能推送代码,能迁移旧项目,能在需要时从外面打开面板。功能不用第一天全开,链路先跑顺,后面加备份、通知和团队权限才不会乱。

这篇就用 Docker Compose 搭一套 Gitea。主线只做稳定、低风险的版本:先跑通 Web 面板和仓库,再迁移已有仓库,局域网能用之后,再用 cpolar 把 Gitea 的 Web 面板安全映射出去。SSH Git 操作会单独说明边界,不把公网 SSH 当默认方案。

图1:Gitea 自建 Git 服务与外网访问链路图

图1:Gitea 部署在局域网服务器中,开发者通过 HTTP/SSH 访问;外网访问优先只通过 cpolar 映射 Web 3000 面板。

1 什么是 Gitea?这篇里它负责什么

Gitea 是一个轻量级的自建 Git 服务,界面和常见代码托管平台接近,能创建仓库、管理成员、看提交记录、提 Issue,也支持从外部 Git 服务迁移仓库。

在这篇文章里,它只负责三件事:

  • 给个人或小团队提供一个私有 Git Web 面板;
  • 接收本地电脑的 git pushgit clone
  • 把 GitHub 或已有 Git 仓库迁移进来,方便后续在内网维护。

我不建议一上来就把它做成复杂的企业代码平台。先用 Docker Compose 跑起来,确认仓库创建、推送、迁移这三件事都通,再考虑邮件、OAuth、备份策略和 CI/CD,排错会轻松很多。

2 环境准备:确认 Docker 和端口

这套教程默认服务器已经安装 Docker Engine,并且支持 Docker Compose v2。Gitea 官方 Docker 文档也按 Compose v2 作为参考方式,命令是 docker compose,不是旧版 docker-compose

在服务器上先确认版本:

docker --version
docker compose version

再看 3000 和 222 端口是否被占用:

ss -lntp | grep -E ':3000|:222' || true

这里用两个端口:

  • 3000:Gitea Web 面板;
  • 222:宿主机对外暴露的 Git SSH 端口,容器内部仍然是 22

如果你的服务器本来就把 222 给了别的服务,后面 Compose 里的 222:22 改成别的宿主机端口,比如 2222:22。别改容器内部的 22,Gitea 容器里的 SSH 服务就是监听这个端口。

图2:部署前先在服务器终端确认 Docker Compose 可用,并检查 3000、222 端口是否被占用。

3 使用 Docker Compose 部署 Gitea

先创建一个单独目录,后续配置和数据都放在这里:

mkdir -p ~/gitea
cd ~/gitea

写入 docker-compose.yml

cat > docker-compose.yml <<'EOF'
networks:
  gitea:
    external: false

services:
  server:
    image: docker.gitea.com/gitea:1.26.2
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__server__SSH_PORT=222
    restart: always
    networks:
      - gitea
    volumes:
      - ./gitea:/data
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "3000:3000"
      - "222:22"
EOF

这里先用 SQLite,适合个人、小团队和教程场景。Gitea 官方 Docker 文档也给了 SQLite 的基础部署方式。等访问量和团队规模上来,再迁移到 MySQL 或 PostgreSQL,会比一开始就堆复杂组件更稳。

启动容器:

docker compose up -d

检查状态和日志:

docker compose ps
docker compose logs -f --tail=100 server

看到 gitea 容器处于运行状态后,打开浏览器访问:

http://服务器IP:3000

如果是在服务器本机操作,也可以访问:

http://127.0.0.1:3000

如果页面打不开,先别急着改配置。按顺序查三件事:容器是否运行、3000 端口是否监听、防火墙是否放行 3000。

docker compose ps
ss -lntp | grep ':3000'

图3:首次访问 http://服务器IP:3000 会进入 Gitea 安装页面,按需填写数据库、站点地址和管理员账号。

4 初始化管理员账号

第一次打开 Gitea 会进入安装页面。这一步不是为了填满配置,而是把数据库、站点地址和管理员账号一次性落盘。

基础场景建议这样填:

  • 数据库类型:SQLite3;
  • 站点标题:按团队或个人习惯填写,比如 My Gitea
  • Gitea 基础 URL:局域网访问就填 http://服务器IP:3000/
  • SSH 服务端口:222
  • 管理员账号:设置一个新的管理员用户名、邮箱和强密码。

这里别把管理员密码设成弱口令。Gitea 面板一旦后面开放给外网访问,弱密码就是最大风险点。

安装完成后,页面会进入 Gitea 首页。登录管理员账号,右上角能看到个人菜单,就说明 Web 面板已经跑通。

图4:管理员账号初始化完成后,进入 Gitea 首页并确认右上角用户菜单可用。

5 创建第一个仓库,并从本地推送代码

先在 Gitea 页面里点右上角加号,创建一个空仓库,比如:

demo-app

仓库先设为私有。新服务刚搭好时,我更推荐默认私有,等权限和访问方式都确认后,再按项目需要开放。

图5:创建第一个私有仓库,例如 demo-app,用于验证本地 Git 推送链路。

在本地电脑准备一个测试项目:

mkdir demo-app
cd demo-app
git init
printf '# demo-app\n' > README.md
git add README.md
git commit -m "init demo app"

如果用 HTTP 推送,远程地址格式如下:

git remote add origin http://服务器IP:3000/用户名/demo-app.git
git push -u origin main

有些本地 Git 默认分支还是 master,先看一下当前分支名:

git branch --show-current

如果显示 master,就用:

git push -u origin master

推送成功后回到 Gitea 仓库页面,能看到 README.md 和第一次提交记录。这一步不是为了测试而测试,而是确认“本地 Git → Gitea Web 仓库”这条链路已经打通。

图6:推送成功后,Gitea 仓库页面应能看到 README.md 和第一次提交记录。

6 从 GitHub 或已有 Git 仓库迁移到 Gitea

Gitea 支持从其他 Git 服务迁移仓库。对于旧项目归档、把个人仓库搬回内网,这个功能比手动 clone 再 push 更省事。

在 Gitea 页面右上角打开创建菜单,选择迁移仓库入口。按页面提示选择来源服务,填写原仓库地址。公开仓库直接填 URL;私有仓库需要填对应平台的用户名和访问令牌。

这里有个提醒:令牌只给迁移所需权限,迁移完就回到原平台删除或收回。不要拿自己的长期高权限令牌到处复用。

如果你更习惯命令行,也可以用 Git 自带的镜像方式迁移。下面以公开仓库为例:

git clone --mirror https://github.com/example/demo-app.git
cd demo-app.git
git push --mirror http://服务器IP:3000/用户名/demo-app.git

--mirror 会带上分支、标签和 refs,适合做完整迁移。目标仓库必须是你在 Gitea 里提前创建好的空仓库,别把它推到已有重要提交的仓库里。

如果推送失败,先检查三点:Gitea 目标仓库地址是否写对、本地是否已经登录或输入了正确密码、目标仓库是否有写入权限。

图7:迁移仓库时填写原仓库地址;私有仓库使用最小权限访问令牌,迁移完成后及时收回。

7 局域网访问:让团队电脑 clone 和 push

局域网里使用 Gitea,最省心的方式是先走 HTTP。团队成员在浏览器打开:

http://服务器IP:3000

登录自己的账号后,进入仓库页面复制 HTTP 克隆地址,再执行:

git clone http://服务器IP:3000/用户名/demo-app.git

如果想用 SSH,宿主机端口是前面映射出来的 222,命令要明确写端口:

git clone ssh://git@服务器IP:222/用户名/demo-app.git

划重点:这里的 git 是 Gitea SSH 服务使用的用户,不是你的 Gitea 登录用户名。你的身份由 SSH Key 绑定关系决定。

添加 SSH Key 的路径在用户个人设置里。把本机公钥复制进去:

cat ~/.ssh/id_ed25519.pub

如果本机还没有 ed25519 密钥,先生成一把:

ssh-keygen -t ed25519 -C "your_email@example.com"

SSH clone 失败时,先检查端口是不是 222,再检查公钥是否加到了当前登录用户下面。不要一上来就改容器配置,十次里有八次是地址或 Key 填错。

图8:如需 SSH clone,在个人设置中添加本机公钥,并使用 ssh://git@服务器IP:222/用户名/仓库.git 格式访问。

8 离开局域网后,用 cpolar 映射 Gitea Web 面板

如果只是公司或家里局域网内使用,做到上一步就够了。人在外面临时查看仓库、处理 Issue、给同事看代码页面时,再考虑把 Gitea Web 面板映射出去。

这里用 cpolar 映射 Gitea 的 3000 Web 端口。Linux 上安装 cpolar 的官方一键命令如下:

curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash

安装后打开本地管理面板:

http://127.0.0.1:9200

在 Web UI 登录账号后,可以创建 HTTP 隧道,本地地址填写:

3000

命令行临时测试也可以直接执行:

cpolar http 3000

启动后,在 cpolar 的在线隧道列表里复制公网 HTTP 地址,用浏览器打开就能进入 Gitea Web 页面。

图9:Docker Compose 部署 Gitea 与 cpolar 映射 3000 Web 面板示意图

图9:Gitea 容器监听 Web 3000 端口,cpolar 将本地 3000 映射为公网访问地址,适合临时查看 Web 面板。

安全边界要说清楚:这里默认只映射 Web 面板,不把 Git SSH 端口长期暴露出去。Web 面板至少要做到管理员强密码、普通成员最小权限、仓库默认私有。公网入口只是方便查看和处理仓库,不等于把整台 Git 服务器变成开放服务。

如果只是偶尔在外面改 README、看提交记录、处理一个轻量代码评审,用 Web 面板已经够了。真正需要外网 git clonegit push 时,再单独评估 HTTP Git 或 TCP/SSH 方案,并且限定账号权限和使用时段。

如果需要稳定访问地址,免费随机公网地址会在 24 小时内变化;固定二级子域名需要基础套餐或以上。这个适合把访问入口固定下来,比如给团队成员收藏一个固定地址。固定 TCP 地址属于更高风险的 Git SSH 场景,需要专业套餐或以上,并且要配合 SSH Key、成员权限和短时开放策略使用。

9 备份、升级和安全提醒

Gitea 的数据目录在当前部署目录下:

~/gitea/gitea

升级前先备份这个目录。最简单的做法是停容器、打包、再启动:

cd ~/gitea
docker compose down
tar -czf gitea-backup-$(date +%F).tar.gz gitea
docker compose up -d

升级 Gitea 镜像时,先修改 docker-compose.yml 里的镜像版本,再执行:

docker compose pull
docker compose up -d

别直接把 ./gitea 数据目录删掉,也别在没有备份的情况下跨多个大版本升级。Gitea 配置文件会保存在容器数据目录内,官方 Docker 文档里也说明配置文件位于 /data/gitea/conf/app.ini

日常安全建议控制在这几条就够用:

  • 仓库默认私有,按成员分配权限;
  • 管理员账号使用强密码,管理员数量越少越好;
  • cpolar 优先映射 Web 端口 3000,SSH/TCP 只在明确需要时短时开启;
  • 重要项目定期离线备份,不把唯一副本只放在一台机器上。

10 总结

到这里,一套轻量的 Gitea 自建 Git 服务已经跑起来了:Docker Compose 负责部署,Gitea 负责仓库管理,局域网内可以 clone 和 push,旧仓库也能迁移进来;离开局域网时,再用 cpolar 暴露 Web 面板,避免一上来就把多个端口都放到公网。

关键步骤可以压缩成三件事:

  • docker compose up -d 启动 Gitea,并把 Web 端口固定在 3000
  • 初始化管理员后,先创建私有仓库,再用 HTTP 或 SSH 在局域网内验证 Git 操作;
  • 外网访问优先只映射 Web 面板,固定入口和 TCP 访问按实际需要再开。

这套方案适合个人服务器、小团队内网仓库和旧项目归档。后续要继续增强,可以再加自动备份、邮件通知、组织权限、Runner 和镜像仓库,但第一天先把“能访问、能推送、能迁移、能备份”跑稳,后面扩展会省很多事。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐