Git Server for Gitea

自建 Git Server 时,小型团队不错的选择:Gitea 开源版本

小型团队场景:轻量完整的 Gitea 开源版本

除非配置 ENABLE_PUSH_CREATE_USER = true,否则仓库要先在WEB中创建,才能使用。

为 Go 语言编写,从 Gogs fork 后独立发展,社区驱动,是目前最主流的轻量自托管 Git 方案。同时,Web 界面做日常管理非常方便。

  • Forgejo 是22 年从 Gitea fork 的完全社区驱动版本,坚持 100% 开源,不设商业公司控制,但文档只有英文。
  • Gitea 架构是单机优先、轻量化,没有 GitLab CE 那种面向大规模团队的后台任务集群、分布式队列设计,人数上去后体验会明显下滑。
v1.27.1 实际内存180M权限能力
轻量且功能均衡:空闲约 80-150 MB,远轻于 GitLab
– 社区极其活跃,版本迭代快,中文文档完善
– 功能全面:组织、团队、分支保护、Wiki、Issue、PR、包注册表、Actions CI
– 部署方式多:二进制、Docker、包管理器均可
– 支持 SQLite 单机模式,也支持 MySQL/PostgreSQL 扩缩容
– 组织级 + 仓库级双层权限
– 支持角色:所有者、管理员、写入者、读取者
– 分支保护规则:可限制谁能推送、是否需要 PR 审核
– 支持私有仓库、内部仓库、公开仓库三种可见性

安装

  1. 官方:使用二进制文件安装Gitea 下载
  2. 环境准备:见 Git Server for Bare,Git 版本 >= 2.0

下载 bin 文件

# 下载 120M
$ sudo mkdir -p /opt/gitea
$ sudo wget https://dl.gitea.com/gitea/1.27.1/gitea-1.27.1-linux-amd64
# SHA-256 验证 86a7ac26e7f9c9cca0f56c4fac07fff205d5fc3bca0e54af23a204f07b833bc9
$ sha256sum gitea-1.27.1-linux-amd64
$ sudo chmod +x gitea-1.27.1-linux-amd64

git用户与路径准备

# 删除已有的 git 用户
ps -u git
userdel -r git
groupdel git

# 创建用户:useradd 是底层工具,adduser 是debian上层封装
# --system 创建系统账户:UID 从系统范围分配(通常 <1000),无密码过期策略,不创建 /home 下的用户目录(除非手动指定)
# --group 创建一个与用户同名的组
# --disabled-password 禁用密码登录
adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git
#useradd --system --shell /bin/bash --comment 'Git Version Control' --create-home --home-dir /home/git --user-group --password '!' git
# 可选,当前用户加入git组,方便后面看文件;注意:要退出会话,重新才生效。
$ sudo gpasswd -a $USER git

# 创建工作路径,按你的实际情况来,官方文档是 /var/lib/gitea/{custom,data,log}
$ sudo mkdir -p /data/www/gitea/{custom,data,log}
$ sudo chown -R git:git /data/www/gitea/
$ sudo chmod -R 750 /data/www/gitea/
# Linux 目录权限规则:**要进入一个子目录,必须对路径上每一级父目录都拥有 `x`(execute/search)权限**,所以也要注意上级目录的权限。否则,服务启动失败。
$ sudo chmod o+x /data

# 创建配置文件路径
$ sudo mkdir /etc/gitea
$ sudo touch /etc/gitea/app.ini
$ sudo chown root:git -R /etc/gitea
$ sudo chmod g+w /etc/gitea/app.ini

创建 systemd 服务

# /usr/local/bin 创建链接
$ sudo ln -s /opt/gitea/gitea-1.27.1-linux-amd64 /usr/local/bin/gitea

$ sudo vim /usr/lib/systemd/system/gitea.service
# 修改 user,home 目录以及其他必须的初始化参数,如果使用自定义端口,则需修改 PORT 参数,反之如果使用默认端口则需删除 -p 标记。

# 激活 gitea 并将它作为系统自启动服务:
$ sudo systemctl enable gitea
$ sudo systemctl start gitea && sudo systemctl status gitea
# 运行成功后,查看日志
$ sudo journalctl -u gitea --no-pager -n 50

没有 /data 与 /data/www 的 other 执行权限,服务启动报错。

  • 原因:Linux 目录权限规则:要进入一个子目录,必须对路径上每一级父目录都拥有 x(execute/search)权限
Aug 07 16:44:33 vps260315 systemd[1]: Started gitea.service - Gitea (Git with a cup of tea).
Aug 07 16:44:33 vps260315 (gitea)[133658]: gitea.service: Changing to the requested working directory failed: Permission denied
Aug 07 16:44:33 vps260315 systemd[1]: gitea.service: Main process exited, code=exited, status=200/CHDIR
Aug 07 16:44:33 vps260315 systemd[1]: gitea.service: Failed with result 'exit-code'.
gitea.service
[Unit]
Description=Gitea (Git with a cup of tea)
After=network.target

[Service]
# 如果你的仓库包含大量文件并因此遇到 HTTP 500 错误,请取消下面这行的注释
# LimitNOFILE=524288:524288
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory=/data/www/gitea
# 如果使用 Unix 套接字:告知 systemd 创建 /run/gitea 目录,其中将存放 gitea.sock 文件(手动创建 /run/gitea 不可行,因为该目录在重启后不会保留)
#RuntimeDirectory=gitea
# Web 的默认端口是 3000,建议到 /etc/gitea/app.ini 中配置,而不是使用 gitea web --port 8080 参数
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/data/www/gitea

[Install]
WantedBy=multi-user.target

配置

Nginx 反代:独立域名

[server]
# 需要使用对外服务的URL,比如Nginx反代的URL,注意以/结尾
ROOT_URL  = https://git.t725.cn/

nginx站点配置

server {
    ...
    location / {
        client_max_body_size 512M;
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Connection $http_connection;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

配置生效:

$ sudo nginx -t && sudo nginx -s reload
$ sudo systemctl restart gitea && sudo systemctl status gitea
$ sudo journalctl -u gitea --no-pager -n 50

app.ini

在配置禁用很多功能后,观察并不能将内存占用降下来,约180M没有变化;所以,不需要去特意关闭功能。

附录

systemd 服务配置文件的目录与区别

优先级目录来源用途
🥇 最高/etc/systemd/system/管理员手动创建/修改系统级自定义配置,永久生效,且不会被包管理器覆盖
🥈/run/systemd/system/运行时动态生成临时覆盖,重启后丢失
🥉/usr/lib/systemd/system/软件包安装 (RHEL/Fedora/Arch)发行版提供的默认单元文件,永远不要直接修改这里的文件,更新会被覆盖
🥉/lib/systemd/system/软件包安装 (Debian/Ubuntu)同上,Debian 系的路径
🔻 最低/usr/local/lib/systemd/system/本地编译安装的软件第三方/自编译软件的单元文件,在 Ubuntu 24.04 无此目录

/var/lib/gitea/{custom,data,log}

Gitea 的运行时数据根目录(由 GITEA_WORK_DIRAPP_DATA_PATH 指定),各自职责严格分离:

/var/lib/gitea/
├── custom/    ← 自定义配置与静态资源覆盖
├── data/      ← 核心业务数据存储
└── log/       ← 运行日志

🎨 custom/ — 自定义层

设计哲学:所有用户自定义内容集中于此,升级 Gitea 二进制时不会被覆盖。
💡 custom/ 的内容在 Gitea 启动时会被”叠加”到内置资源之上,相当于一个透明的覆盖层。

子路径内容说明
conf/app.ini主配置文件若未通过 --config 另行指定,则从这里读取
templates/模板覆盖放置同名模板文件即可覆盖内置模板,无需改源码
public/静态资源覆盖自定义 CSS/JS/图片/logo,优先级高于内置 public/
options/选项文件覆盖locale/gitignore/license/readme/ 模板
mail/邮件模板自定义通知邮件的 HTML/文本模板

💾 data/ — 业务数据

⚠️ 这是备份的核心目标,丢失即丢失仓库和用户数据。

子路径内容说明
gitea-repositories/Git 裸仓库每个仓库一个 .git 目录,按 {owner}/{repo}.git 组织
lfs/Git LFS 对象LFS 指针指向的实际大文件,按 OID 哈希分目录存储
attachments/附件存储Issue/PR 上传的文件、头像、仓库归档包等
avatars/用户/组织头像上传的自定义头像文件
repo-archive/仓库归档缓存生成的 zip/tar.gz 下载包缓存
packages/包注册表数据Container Registry / npm / PyPI 等包的存储
actions/Gitea ActionsRunner 日志、Artifact、Secrets 加密数据
sessions/会话数据当 session provider 为 file 时的会话文件
queues/持久化队列异步任务队列的磁盘持久化数据(LevelDB)
indexers/搜索索引Bleve/Elasticsearch 的代码搜索和 Issue 搜索索引
tmp/临时文件上传中转、导出任务等产生的临时文件

⚠️ 注意:如果使用外部数据库(MySQL/PostgreSQL),用户、Issue、PR 等元数据存在数据库中,但上述文件系统数据不会存入数据库,两者必须同时备份。

📝 log/ — 日志

文件/子路径内容说明
gitea.log主应用日志Web 请求、内部操作、错误信息
gitea.log.1 / .gz轮转历史日志由内置 logger 自动轮转
http.logHTTP 访问日志仅在 [log] ENABLE_ACCESS_LOG=true 时生成
router.log路由日志请求路径、状态码、耗时
xorm.logSQL 查询日志仅在 [database] LOG_SQL=true 时生成(⚠️ 性能影响大)
mailer.log邮件发送日志SMTP 发送记录与错误
console.log控制台输出副本当同时配置了文件和控制台输出时

💡 日志行为完全由 app.ini[log] 段控制,可配置级别、格式、轮转策略、独立输出器等。生产环境建议至少保留 Info 级别的主日志 + 独立的 Error 级别日志。

示例 gitea.service

只有注释行翻译为中文了

[Unit]
Description=Gitea (Git with a cup of tea)
After=network.target
###
# 别忘了添加数据库服务的依赖项
#Wants=mysql.service / mariadb.service / postgresql.service / memcached.service / redis.service
#After=mysql.service / mariadb.service / postgresql.service / memcached.service / redis.service
#
###
# 如果主 HTTP/HTTPS 使用套接字激活(Socket Activation)
#After=gitea.main.socket
#Requires=gitea.main.socket
#
###
# (你也可以为 Gitea 提供 HTTP 回退套接字和/或 SSH 套接字)
# /etc/systemd/system/gitea.main.socket 示例如下
###
##
## [Unit]
## Description=Gitea Web 套接字
## PartOf=gitea.service
##
## [Socket]
## Service=gitea.service
## ListenStream=<某个端口>
## NoDelay=true
##
## [Install]
## WantedBy=sockets.target
##
###

[Service]
# 如果你的仓库包含大量文件并因此遇到 HTTP 500 错误,请取消下面这行的注释
# LimitNOFILE=524288:524288
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
# 如果使用 Unix 套接字:告知 systemd 创建 /run/gitea 目录,其中将存放 gitea.sock 文件 (手动创建 /run/gitea 不可行,因为该目录在重启后不会保留)
#RuntimeDirectory=gitea
ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
# 如果你将 Git 安装到了默认 PATH 以外的目录前缀下(例如,当你与发行版自带的 Git 并行安装了其他版本的 Git 时),请取消下面这行的注释,并将该前缀添加到 PATH 中
# 如果你想启用 Git LFS 支持,别忘了把 git-lfs 二进制文件也放到下面的 PATH 中
#Environment=PATH=/path/to/git/bin:/bin:/sbin:/usr/bin:/usr/sbin
#
###
# 如果你想让 Gitea 绑定到 1024 以下的端口,请取消下面两行的注释,或者像上面那样使用套接字激活来向 Gitea 传递端口
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#AmbientCapabilities=CAP_NET_BIND_SERVICE
###
# 在某些情况下,当同时使用 CapabilityBoundingSet 和 AmbientCapabilities 选项时,你可能需要将下面的值设为 false,以允许将能力(capabilities)应用到 gitea 进程上。
# 如果下面的值设为 true,将会对 gitea 服务进行沙箱隔离,阻止任何进程在宿主用户命名空间中以特权身份运行。
###
#PrivateUsers=false
###

[Install]
WantedBy=multi-user.target

发表回复