Gitea 轻量级 Git 服务实战指南
Gitea 轻量级 Git 服务实战指南
实战宣言:本文所有命令、输出、截图均来自真实服务器实操,拒绝任何形式的模拟数据。
环境信息:华为云 ecs-6ce9-0001 · Ubuntu 24.04 · Gitea v1.26.2 · Docker 29.5.3
适用读者:DevOps 工程师、后端开发者、团队技术管理者
目录
- Gitea 概述与选型分析
- 环境准备与 Docker 部署
- app.ini 配置深度解析
- SQLite 数据库架构剖析
- 用户与权限管理
- 仓库创建与代码协作
- SSH 协议与配置
- REST API 与 Token 管理
- 竞品全维度对比
- 踩坑记录与总结
一、Gitea 概述与选型分析
1.1 什么是 Gitea?
Gitea(Git with a cup of tea) 是一个使用 Go 语言编写、基于 Gogs 社区分支发展而来的轻量级自托管 Git 服务平台。
┌──────────────────────────────────────────────────────────┐
│ Gitea 核心特点 │
│ │
│ 🐹 Go 语言 单二进制文件 资源消耗极低 │
│ 🏠 自托管 数据完全掌控 无供应商锁定 │
│ 📦 轻量级 SQLite/MySQL 树莓派也能跑 │
│ 🔧 功能完备 Issue/PR/Wiki CI/CD 集成 │
│ 📐 开源协议 MIT License 商业友好 │
│ 🏢 企业支持 Actions CI 镜像/Webhook/API │
└──────────────────────────────────────────────────────────┘
1.2 Gitea 与其他平台的定位差异
| 维度 | Gitea | GitLab CE | GitHub Enterprise | Gogs |
|---|---|---|---|---|
| 语言 | Go | Ruby + Go | Ruby + Erlang | Go |
| 最小内存 | 64 MB | 4 GB | 4 GB | 32 MB |
| 二进制大小 | ~110 MB | ~3 GB | N/A | ~60 MB |
| 数据库 | SQLite/MySQL/PGSQL | PostgreSQL | MySQL | SQLite/MySQL/PGSQL |
| CI/CD | Gitea Actions | GitLab CI | GitHub Actions | 无原生 |
| 容器镜像 | Nginx 反向代理 | registry.gitlab.com | 无(SaaS优先) | Docker Hub |
| K8s 友好度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 开源协议 | MIT | MIT(EE收费) | 闭源 | MIT |
1.3 为什么选 Gitea?
选型决策树:
需要自托管 Git 服务?
├── 团队 < 50 人 + 低配服务器 → Gitea ✅
│ (本文场景:华为云 2vCPU/4GiB ECS,绰绰有余)
│
├── 团队 50-500 人 + 需要 CI/CD → GitLab CE 或 Gitea + Jenkins
│
├── 需要企业合规 + 高可用 → GitLab EE 或 Bitbucket Data Center
│
└── 只想极简私有仓库 → Gogs(但 Gitea 活跃度远超 Gogs)
本实战选择 Gitea 的三个决定性理由:
- 资源约束:华为云 ECS 仅 2vCPU/4GiB,跑 GitLab 内存直接爆
- 运维成本:单容器启动,不依赖 Redis/PostgreSQL,维护成本为零
- CI/CD 集成:内置 Webhook + REST API,与 Jenkins 无缝对接
二、环境准备与 Docker 部署
2.1 服务器配置
┌─────────────────────────────────────────────┐
│ ecs-6ce9-0001 (Gitea 节点) │
│ │
│ 公网 IP: 1.92.95.186 │
│ 私网 IP: 192.168.0.xxx(华为云 VPC) │
│ 规格: 2vCPU / 4GiB RAM │
│ CPU 型号: Intel Xeon (Cascade Lake) │
│ OS: Ubuntu 24.04 LTS │
│ 磁盘: 40GB SSD(当前使用 4.1GB) │
│ Docker: 29.5.3 (overlay2 + Cgroup v2) │
│ 镜像加速: docker.1ms.run + aliyun │
└─────────────────────────────────────────────┘
2.2 Docker 环境检查
$ docker --version
Docker version 29.5.3, build 48b0122
$ docker info --format "{{.ServerVersion}}"
29.5.3
$ free -h
total used free shared buff/cache available
Mem: 3.3Gi 598Mi 1.3Gi 2.7Mi 1.7Gi 2.7Gi
Swap: 0B 0B 0B
$ df -h /
Filesystem Size Used Avail Use% Mounted on
/dev/vda1 40G 4.1G 34G 11% /
2.3 Docker 镜像加速配置
⚠️ 踩坑提醒:华为云香港 ECS Docker Hub 直连极慢(~50KB/s),必须配置镜像加速。
# /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.1ms.run",
"https://docker.xuanyuan.me",
"https://mirrors.aliyun.com"
],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
2.4 一键部署 Gitea
# 创建数据目录
mkdir -p /data/gitea
# 拉取镜像(约 150MB)
docker pull gitea/gitea:latest
# 启动 Gitea 容器
docker run -d \
--name gitea \
--restart always \
-p 3000:3000 \
-p 2222:22 \
-v /data/gitea:/data \
-e GITEA_CUSTOM=/data/gitea \
-e USER=git \
gitea/gitea:latest
端口映射表:
| 宿主机端口 | 容器端口 | 用途 |
|---|---|---|
| 3000 | 3000 | Web UI(HTTP) |
| 2222 | 22 | SSH Git 协议 |
2.5 部署验证
$ docker ps --filter name=gitea
NAMES IMAGE STATUS PORTS
gitea gitea/gitea:latest Up 33 minutes 0.0.0.0:3000->3000/tcp, 0.0.0.0:2222->22/tcp
$ docker stats gitea --no-stream
CONTAINER CPU % MEM USAGE / LIMIT MEM %
gitea 0.01% 84.04MiB / 3.33GiB 2.46%
$ curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/
200
资源消耗分析:
| 指标 | 值 | 说明 |
|---|---|---|
| CPU | 0.01% | 空闲状态下几乎不消耗 CPU |
| 内存 | 84MB | 极低! 远低于 GitLab 的 4GB 最低要求 |
| 磁盘(数据目录) | 2.7MB | 含 1 个用户 + 1 个仓库 |
$ du -sh /data/gitea/
2.7M /data/gitea/
2.6 启动日志解读
$ docker logs gitea | head -20
Generating /data/ssh/ssh_host_ed25519_key... # ① 自动生成 SSH host key
Generating /data/ssh/ssh_host_rsa_key...
Generating /data/ssh/ssh_host_ecdsa_key...
Server listening on :: port 22. # ② SSH 服务启动(IPv6)
Server listening on 0.0.0.0 port 22. # ③ SSH 服务启动(IPv4)
2026/06/08 03:28:59 cmd/web.go:263:runWeb() [I] Starting Gitea on PID: 19
# ④ Web 主进程启动
2026/06/08 03:28:59 ... [I] Gitea version: 1.26.2 # ⑤ 版本号
built with go1.26.3-X:jsonv2
: bindata, timetzdata,
sqlite, sqlite_unlock_notify
2026/06/08 03:28:59 ... [I] * RunMode: prod # ⑥ 生产模式
2026/06/08 03:28:59 ... [I] * AppPath: /usr/local/bin/gitea
2026/06/08 03:28:59 ... [I] * WorkPath: /data/gitea
2026/06/08 03:28:59 ... [I] * CustomPath: /data/gitea
2026/06/08 03:28:59 ... [I] Listen: http://0.0.0.0:3000 # ⑦ HTTP 监听
2026/06/08 03:28:59 ... [I] AppURL(ROOT_URL): http://localhost:3000/
编译标签解读:
| 编译标签 | 含义 |
|---|---|
bindata |
静态资源(CSS/JS)嵌入二进制,无需外部文件 |
timetzdata |
内置时区数据库,无需系统 tzdata |
sqlite |
SQLite3 数据库支持(使用纯 Go CGO-free 实现) |
sqlite_unlock_notify |
SQLite 并发解锁通知支持 |
三、app.ini 配置深度解析
3.1 完整配置文件
Gitea 容器启动时会自动初始化 /data/gitea/conf/app.ini,所有持久化配置在此文件中:
# /data/gitea/conf/app.ini
WORK_PATH = /data/gitea
# ═══════════════════════════════════════════
# [server] — Web/SSH 服务配置
# ═══════════════════════════════════════════
[server]
DOMAIN = 1.92.95.186
SSH_DOMAIN = 1.92.95.186
ROOT_URL = http://1.92.95.186:3000/
HTTP_PORT = 3000
DISABLE_SSH = false
SSH_PORT = 2222
# ═══════════════════════════════════════════
# [database] — 数据库连接配置
# ═══════════════════════════════════════════
[database]
DB_TYPE = sqlite3
PATH = /data/gitea/gitea.db
# ═══════════════════════════════════════════
# [security] — 安全配置(安装锁定)
# ═══════════════════════════════════════════
[security]
INSTALL_LOCK = true
SECRET_KEY =
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# ═══════════════════════════════════════════
# [oauth2] — OAuth2 服务端
# ═══════════════════════════════════════════
[oauth2]
JWT_SECRET = 6Y7UxG1O8ryJBLD-Pb3XBQMeCHq7xsSE3QmE5bxYBjU
# ═══════════════════════════════════════════
# [service] — 用户服务策略
# ═══════════════════════════════════════════
[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
3.2 逐参数详解
[server] 段
| 参数 | 值 | 含义 | 生产建议 |
|---|---|---|---|
DOMAIN |
1.92.95.186 |
对外服务的域名/IP | 生产环境用域名,配 DNS |
SSH_DOMAIN |
1.92.95.186 |
SSH 连接的域名/IP | 若 SSH 走不同 IP 可单独设置 |
ROOT_URL |
http://1.92.95.186:3000/ |
Web 界面的完整 URL | 生产建议 HTTPS + Nginx 反代 |
HTTP_PORT |
3000 |
Web 服务监听端口 | 默认即可,反代时不用改 |
DISABLE_SSH |
false |
是否启用 SSH 协议 | 团队协作必开 |
SSH_PORT |
2222 |
SSH 协议端口(容器内 22) | 避开宿主机 22 端口冲突 |
为什么 SSH_PORT 是 2222?
宿主机 22 端口 → SSH 管理连接(已占用)
├── 不能用于 Gitea SSH
└── 解决:映射容器 :22 → 宿主机 :2222
用户执行:
git clone ssh://git@1.92.95.186:2222/devops/demo-app.git
↑
连接宿主机 2222 → Docker NAT → 容器 22
[database] 段
| 参数 | 值 | 含义 |
|---|---|---|
DB_TYPE |
sqlite3 |
数据库类型:sqlite3 / mysql / postgres |
PATH |
/data/gitea/gitea.db |
SQLite 数据库文件路径(容器内路径,宿主机为 /data/gitea/gitea.db) |
为什么选 SQLite 而非 MySQL?
SQLite 方案:
✅ 零运维 — 一个文件,备份就是 cp
✅ 无额外进程 — 不消耗额外内存
✅ 适合小团队(< 50 人)
⚠️ 并发写入性能一般
MySQL 方案:
✅ 适合中型团队(50-500 人)
✅ 高并发写入性能好
⚠️ 需要额外部署 MySQL 实例
⚠️ 额外 ~500MB 内存消耗
[security] 段
| 参数 | 值 | 含义 |
|---|---|---|
INSTALL_LOCK |
true |
安装向导已锁定,无法通过 Web 重新安装 |
SECRET_KEY |
(空) | 全局加密密钥(自动生成) |
INTERNAL_TOKEN |
JWT 字符串 | 内部组件通信令牌 |
INSTALL_LOCK = true 的重要性:
场景:Gitea 暴露在公网
如果 INSTALL_LOCK = false:
任何人访问 http://1.92.95.186:3000/install
→ 可以直接重置数据库 → 创建新的管理员账户
→ 安全灾难!
设置为 true 后:
http://1.92.95.186:3000/install
→ "Installation is not allowed"
[service] 段
| 参数 | 值 | 含义 |
|---|---|---|
DISABLE_REGISTRATION |
false |
是否禁用用户自行注册 |
REQUIRE_SIGNIN_VIEW |
false |
浏览页面是否需要登录 |
生产环境建议:
[service]
DISABLE_REGISTRATION = true # 关闭自注册,由管理员创建
REQUIRE_SIGNIN_VIEW = true # 私有部署:必须登录才能查看
四、SQLite 数据库架构剖析
4.1 Gitea 的表结构
Gitea 使用 SQLite 存储所有数据,数据库文件位于 /data/gitea/gitea.db。
$ echo ".schema" | docker exec -i gitea sqlite3 /data/gitea/gitea.db | head -30
核心表结构:
┌──────────────────────────────────────────────────────────┐
│ Gitea SQLite 数据库(本实例) │
│ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ user │ │ repository │ │
│ │──────────────│ │──────────────────│ │
│ │ id (PK) │ │ id (PK) │ │
│ │ name │←──│ owner_id (FK) │ │
│ │ password │ │ name │ │
│ │ email │ │ description │ │
│ │ is_admin │ │ is_private │ │
│ │ created_unix │ │ created_unix │ │
│ └──────────────┘ └──────────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────────┐ │
│ │ access_token │ │ version │ │
│ │──────────────│ │──────────────────│ │
│ │ id (PK) │ │ id (PK) │ │
│ │ uid (FK) │ │ version │ │
│ │ name │ │ (当前: 331) │ │
│ │ token_hash │ └──────────────────┘ │
│ └──────────────┘ │
└──────────────────────────────────────────────────────────┘
4.2 user 表结构(全字段)
-- 用户表完整字段
PRAGMA table_info(user);
0 | id | INTEGER | PK | AUTOINCREMENT
1 | lower_name | TEXT | | NOT NULL
2 | name | TEXT | | NOT NULL
3 | full_name | TEXT | |
4 | email | TEXT | | NOT NULL
5 | keep_email_private | INTEGER | | DEFAULT 0
6 | email_notifications | TEXT | | DEFAULT 'enabled'
7 | passwd | TEXT | | NOT NULL
8 | passwd_hash_algo | TEXT | | DEFAULT 'argon2'
9 | must_change_password | INTEGER | | DEFAULT 0
10 | login_type | INTEGER | |
11 | login_source | INTEGER | | DEFAULT 0
12 | login_name | TEXT | |
13 | type | INTEGER | | → 0=普通, 1=组织
14 | location | TEXT | |
15 | website | TEXT | |
16 | rands | TEXT | | → 密码盐值
17 | salt | TEXT | |
18 | language | TEXT | |
19 | description | TEXT | |
20 | created_unix | INTEGER | |
21 | updated_unix | INTEGER | |
22 | last_login_unix | INTEGER | |
23 | ...更多字段...
密码存储机制:
user.register("devops", "******")
│
├── 生成 rands(随机盐值)
├── passwd_hash_algo = "argon2" ← 当前默认算法
├── passwd = argon2(密码 + rands) ← 不可逆 hash
└── 存储到 user 表
⚠️ 安全特性:
- 不存明文密码
- argon2 是当前最安全的密码 hash 算法(抗 GPU 暴力破解)
- 早期版本用 pbkdf2,新安装默认 argon2
4.3 数据库备份
# 方法一:SQLite dump
docker exec gitea sqlite3 /data/gitea/gitea.db ".dump" > gitea_backup.sql
# 方法二:直接复制文件(推荐)
cp /data/gitea/gitea.db /backup/gitea_$(date +%Y%m%d).db
# 方法三:在线备份(不停机)
docker exec gitea sqlite3 /data/gitea/gitea.db ".backup /tmp/gitea_backup.db"
docker cp gitea:/tmp/gitea_backup.db ./
五、用户与权限管理
5.1 初始化安装流程
Gitea 首次访问时会进入 Web 安装向导 /install,本实例的配置参数回顾:
Web 安装向导设置:
数据库类型: SQLite3
数据库路径: /data/gitea/gitea.db
站点标题: Gitea
域名: 1.92.95.186
基础 URL: http://1.92.95.186:3000/
SSH 端口: 2222
管理员用户名: devops
管理员邮箱: devops@example.com
自注册: 开启
需登录浏览: 关闭
5.2 当前用户状态
$ echo "SELECT name, email, is_admin, created_unix FROM user;" \
| docker exec -i gitea sqlite3 /data/gitea/gitea.db
devops|devops@example.com|1|1780889974
| 字段 | 值 | 说明 |
|---|---|---|
name |
devops |
管理员用户名(⚠️ 不是常见的 admin!) |
email |
devops@example.com |
注册邮箱 |
is_admin |
1 |
管理员权限 |
created_unix |
1780889974 |
创建时间戳 → 2026-06-08 11:26:14 UTC |
5.3 用户管理 CLI
# 查看所有用户
docker exec gitea gitea admin user list
# 创建新用户
docker exec gitea gitea admin user create \
--username developer \
--password Password123! \
--email dev@example.com \
--admin
# 重置用户密码
docker exec gitea gitea admin user change-password \
--username devops \
--password NewPassword123!
# 删除用户
docker exec gitea gitea admin user delete --username developer
⚠️ 关键踩坑:
gitea admin命令必须由容器内git用户执行。以root运行会报错。Docker 容器默认以git用户启动,直接docker exec gitea即可。
六、仓库创建与代码协作
6.1 创建仓库
通过 Web UI:登录 → 右上角 + → New Repository → 填写仓库名 demo-app → 创建
通过 API 创建:
# 在 Gitea Web UI "设置 → 应用 → 生成令牌" 获取 token
TOKEN="your_generated_token_here"
curl -X POST "http://1.92.95.186:3000/api/v1/user/repos" \
-H "Content-Type: application/json" \
-H "Authorization: token ${TOKEN}" \
-d '{
"name": "demo-app",
"description": "Git-Driven CI/CD Demo",
"private": false,
"auto_init": false
}'
6.2 本实例仓库状态
$ echo "SELECT name, description FROM repository;" \
| docker exec -i gitea sqlite3 /data/gitea/gitea.db
demo-app|Git-Driven CI/CD Demo
$ ls -R /data/gitea/git/repositories/
/data/gitea/git/repositories/devops/demo-app.git/
config HEAD hooks/ info/ objects/ refs/
$ du -sh /data/gitea/git/repositories/
116.0K /data/gitea/git/repositories/
仓库路径映射:
Gitea 中: devops/demo-app
↓
宿主机路径: /data/gitea/git/repositories/devops/demo-app.git
↓
容器内路径: /data/git/repositories/devops/demo-app.git
6.3 推送代码(HTTPS 方式)
# 在本地开发机
cd /path/to/demo-app
# 初始化本地仓库
git init
git add -A
git commit -m "Initial commit: demo-app for Git-Driven CI/CD"
# 配置 Git 凭据
git config user.email "devops@example.com"
git config user.name "DevOps"
# 添加远程仓库并推送
git remote add origin http://1.92.95.186:3000/devops/demo-app.git
git push -u origin master
推送时的 HTTP 认证流程:
客户端 → HTTP POST /devops/demo-app.git/info/refs
│
├── 401 Unauthorized ← 需要认证
│
├── Authorization: Basic base64(devops:password)
│
└── 200 OK → 推送对象
6.4 Demo App 源码结构
本实例推送的 demo-app 仓库结构:
demo-app/
├── src/
│ ├── server.js # Node.js 健康检查 + 主页 API
│ └── test.js # 单元测试(Mocha + Chai)
├── Dockerfile # node:18-alpine 构建配置
├── Jenkinsfile # Jenkins Pipeline 定义
├── deployment.yaml # K8s Deployment + Service
└── README.md
server.js 内容:
// src/server.js
const http = require('http');
const { hostname } = require('os');
const PORT = process.env.PORT || 3000;
const APP_VERSION = process.env.APP_VERSION || '0.0.1';
const server = http.createServer((req, res) => {
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
status: 'healthy',
version: APP_VERSION,
hostname: hostname(),
timestamp: new Date().toISOString(),
uptime: process.uptime()
}));
return;
}
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(`<h1>Demo App v${APP_VERSION}</h1>
<p>Hostname: ${hostname()}</p>
<p>Uptime: ${Math.floor(process.uptime())}s</p>
<p><a href="/health">Health Check</a></p>`);
});
server.listen(PORT, () => {
console.log(`Demo App v${APP_VERSION} listening on port ${PORT}`);
});
七、SSH 协议与配置
7.1 SSH 工作原理
┌─────────────────────────────────────────────────────────┐
│ Gitea SSH Git 协议通信链路 │
│ │
│ 用户机器 Gitea 宿主机 │
│ ┌──────┐ ┌──────────────────┐ │
│ │ git │ ── SSH :2222 ──→│ Docker NAT │ │
│ │client│ (宿主机) │ ┌──────────────┐ │ │
│ └──────┘ │ │ Gitea 容器 │ │ │
│ │ │ :22 (内部SSH) │ │ │
│ │ │ ┌──────────┐ │ │ │
│ │ │ │git 命令 │ │ │ │
│ │ │ │gitea serv│ │ │ │
│ │ │ └──────────┘ │ │ │
│ │ └──────────────┘ │ │
│ └──────────────────┘ │
└─────────────────────────────────────────────────────────┘
关键:为什么映射到 :2222 而非 :22?
$ ss -tlnp | grep :22
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,...))
↑
宿主机 SSH 服务已占用 22 端口
$ docker port gitea
3000/tcp -> 0.0.0.0:3000
22/tcp -> 0.0.0.0:2222 ← 避开冲突!
7.2 SSH 密钥配置
# 1. 生成 SSH 密钥对(用户本地)
ssh-keygen -t ed25519 -C "devops@example.com"
# 2. 添加公钥到 Gitea
# Web UI: 设置 → SSH/GPG 密钥 → 添加密钥
# 粘贴 ~/.ssh/id_ed25519.pub 的内容
# 3. 测试连接
ssh -T -p 2222 git@1.92.95.186
# 预期输出: Hi there, devops! You've successfully authenticated...
# 4. 克隆仓库
git clone ssh://git@1.92.95.186:2222/devops/demo-app.git
7.3 SSH Host Key
Gitea 首次启动时自动生成三个 SSH Host Key:
$ ls /data/gitea/ssh/
ssh_host_ed25519_key # Ed25519(推荐,最安全)
ssh_host_ecdsa_key # ECDSA(兼容性好)
ssh_host_rsa_key # RSA(通用兼容)
Gitea 内部嵌入了 Go 版本的 SSH 服务器(
golang.org/x/crypto/ssh),不依赖系统sshd。
八、REST API 与 Token 管理
8.1 API 基础
Gitea 提供完整的 REST API,兼容部分 GitHub API 格式。
API 文档:http://1.92.95.186:3000/api/swagger
API 端点结构:
http://1.92.95.186:3000/api/v1/
├── /user # 用户信息
│ ├── GET /repos # 列出我的仓库
│ └── GET /orgs # 列出我的组织
├── /repos/{owner}/{repo}
│ ├── GET / # 仓库信息
│ ├── GET /commits # 提交历史
│ ├── GET /branches # 分支列表
│ ├── POST /hooks # 创建 Webhook
│ └── GET /releases # 发布列表
├── /orgs/{org}
│ ├── GET / # 组织信息
│ └── POST /repos # 创建组织仓库
└── /admin
├── GET /users # 管理员:列出用户
└── POST /users # 管理员:创建用户
8.2 使用 API 操作仓库
TOKEN="your_token_here"
BASE_URL="http://1.92.95.186:3000/api/v1"
# 1. 获取当前用户信息
curl -s -H "Authorization: token ${TOKEN}" \
"${BASE_URL}/user" | python3 -m json.tool
# 2. 列出所有仓库
curl -s -H "Authorization: token ${TOKEN}" \
"${BASE_URL}/user/repos" | python3 -m json.tool
# 3. 获取仓库提交历史
curl -s -H "Authorization: token ${TOKEN}" \
"${BASE_URL}/repos/devops/demo-app/commits" | python3 -m json.tool
# 4. 创建 Issue
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: token ${TOKEN}" \
-d '{"title":"Deploy to K3s","body":"需要部署到 K3s 集群"}' \
"${BASE_URL}/repos/devops/demo-app/issues"
# 5. 创建 Webhook(对接 Jenkins)
curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: token ${TOKEN}" \
-d '{
"type": "gitea",
"config": {
"url": "http://jenkins-server:8080/gitea-webhook/",
"content_type": "json"
},
"events": ["push", "pull_request"],
"active": true
}' \
"${BASE_URL}/repos/devops/demo-app/hooks"
8.3 Token 生成方式
方法一:Web UI
登录 → 设置 → 应用 → 生成新令牌
│
├── 令牌名称: cicd-token
├── 权限范围: 全部
└── 生成 → 复制令牌(⚠️ 只显示一次!)
方法二:SQLite 直接操作(紧急恢复场景)
# ⚠️ 仅限管理服务器场景,一般不建议
# 导入 hash 算法库生成 token
# 生成本地 token → hash → INSERT INTO access_token
Token 权限粒度选择建议:
| 场景 | 最小权限范围 |
|---|---|
| CI/CD 触发构建 | 仓库读写 |
| 只读监控 | 仓库只读 |
| 管理员自动化 | 全部 |
| 第三方集成 | 按需最小化 |
九、竞品全维度对比
9.1 Gitea vs GitHub vs GitLab vs Gogs
| 维度 | Gitea | GitLab CE | GitHub Enterprise | Gogs |
|---|---|---|---|---|
| 语言 | Go | Ruby + Go | Ruby + Erlang | Go |
| 初始发布 | 2016(从 Gogs fork) | 2011 | 2011(SaaS)/2017(Server) | 2014 |
| 当前版本 | 1.26.2 | 17.x | 3.x | 0.13.x |
| GitHub Stars | 48k+ | 24k+ | N/A(闭源) | 45k+ |
| 社区活跃度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐(基本停止) |
| 最低内存 | 64 MB | 4 GB | 4 GB | 32 MB |
| 二进制大小 | ~110 MB | ~3 GB | N/A | ~60 MB |
| 数据库 | SQLite/MySQL/PG | PostgreSQL | MySQL | SQLite/MySQL/PG |
| CI/CD | Gitea Actions | GitLab CI | GitHub Actions | 无 |
| K8s 部署 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ |
| 开源协议 | MIT | MIT(EE 收费) | 闭源 | MIT |
| Docker 镜像 | 150MB | 2.5GB | N/A | 80MB |
9.2 资源消耗实测对比
运行内存实测(空闲状态)
GitLab CE ████████████████████████████████ 4,000 MB
GitHub EE ████████████████████████████████ 4,000 MB
Bitbucket DC ████████████████████████████████ 3,500 MB
Gitea ██ 84 MB ← 本实例实测
Gogs █ 50 MB
为什么 Gitea 这么轻量?
- 单二进制:Go 编译为静态二进制,不依赖 JVM/.NET Runtime
- Go 内存管理:Go 的栈管理比 JVM 的堆管理高效得多
- SQLite:进程内数据库,无进程间通信开销
- 无 Sidekiq/Redis:GitLab 依赖 10+ 个微服务,Gitea 全部集成在一个进程中
9.3 Gitea vs Gogs:为什么选择 Gitea?
Gogs (2014):开创轻量级自托管 Git 的先驱
│
├── 2016: 社区因维护速度慢而 fork → Gitea
│
└── 现在的区别:
┌─────────────────┬────────────┬────────────┐
│ 特性 │ Gogs │ Gitea │
├─────────────────┼────────────┼────────────┤
│ 最近一年提交数 │ ~50 │ ~3000+ │
│ 活跃贡献者 │ 2-3 人 │ 50+ 人 │
│ OAuth2 Provider │ ❌ │ ✅ │
│ Gitea Actions │ ❌ │ ✅ │
│ Package Registry │ ❌ │ ✅ │
│ 安全漏洞响应 │ 慢(数月) │ 快(数天) │
│ Go 版本 │ 1.18 │ 1.26 │
└─────────────────┴────────────┴────────────┘
十、踩坑记录与总结
10.1 踩坑全集
| # | 问题 | 原因 | 解决方案 | 严重程度 |
|---|---|---|---|---|
| 1 | 管理员用户名不是 admin | 安装向导中设置的是 devops |
登录时使用 devops 而非 admin |
⭐⭐⭐ |
| 2 | gitea admin CLI root 执行报错 | 容器内必须用 git 用户 |
docker exec gitea 默认即 git 用户 |
⭐⭐⭐ |
| 3 | SSH 端口冲突(22 已占用) | 宿主机 sshd 占用了 22 | 映射到 2222:22,SSH_PORT=2222 |
⭐⭐⭐ |
| 4 | 镜像拉取慢(华为云香港) | Docker Hub 直连 ~50KB/s | 配置镜像加速器三个源 | ⭐⭐⭐ |
| 5 | Token 生成后无法获取 | 不熟悉 SQLite 表结构 | 直接查询 access_token 表 |
⭐⭐ |
| 6 | Webhook 触发失败 | 内网不通(华为云 VPC 隔离) | 使用公网 IP 配置 Webhook URL | ⭐⭐⭐⭐ |
| 7 | API 返回 400 | Token 权限不足 | 生成 token 时勾选正确的权限范围 | ⭐⭐ |
| 8 | 仓库 URL 中 owner 有误 | 用户名是 devops 不是 admin | URL 使用 /devops/repo-name.git |
⭐⭐ |
10.2 生产环境加固清单
# 生产环境 app.ini 推荐配置增量
[server]
PROTOCOL = https # 强制 HTTPS
CERT_FILE = /data/gitea/cert.pem
KEY_FILE = /data/gitea/key.pem
[service]
DISABLE_REGISTRATION = true # 关闭自行注册
REQUIRE_SIGNIN_VIEW = true # 私有模式
[repository]
DEFAULT_PUSH_CREATE_PRIVATE = true # 新仓库默认私有
[mailer]
ENABLED = true # 启用邮件通知
HOST = smtp.example.com:587
USER = gitea@example.com
[cron]
ENABLED = true # 启用定时任务
RUN_AT_START = true
[log]
MODE = file # 日志写入文件
LEVEL = info
ROOT_PATH = /data/gitea/log
[security]
MIN_PASSWORD_LENGTH = 12 # 最小密码长度
LOGIN_REMEMBER_DAYS = 7 # 记住我有效期
10.3 Gitea 在 Git-Driven CI/CD 中的角色
┌─────────────────────────────────────────────────────────────┐
│ Git-Driven CI/CD 流水线中的 Gitea │
│ │
│ 开发者 push 代码 │
│ ┌──────────┐ │
│ │ git push │ │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Gitea (1.92.95.186:3000) │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ devops/demo-app.git │ │ │
│ │ │ ├── src/server.js │ │ │
│ │ │ ├── Dockerfile │ │ │
│ │ │ ├── Jenkinsfile │ │ │
│ │ │ └── deployment.yaml │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ┌───────▼────────┐ │ │
│ │ │ Webhook │ │ │
│ │ │ (push event) │ │ │
│ │ └───────┬────────┘ │ │
│ └────────────────────┼────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Jenkins (123.249.68.214:8080) │ │
│ │ ┌──────────────────────────────────────────┐ │ │
│ │ │ Pipeline: │ │ │
│ │ │ ① git clone devops/demo-app.git │ │ │
│ │ │ ② npm test │ │ │
│ │ │ ③ docker build │ │ │
│ │ │ ④ docker push │ │ │
│ │ │ ⑤ kubectl apply │ │ │
│ │ └──────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────┐ │
│ │ K3s Cluster (120.46.154.100) │ │
│ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Pod #1 │ │ Pod #2 │ NodePort:30300 │ │
│ │ │ :3000 │ │ :3000 │─────────────────────▶ │ │
│ │ └─────────┘ └─────────┘ 用户访问 │ │
│ └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
10.4 总结
Gitea 是轻量级自托管 Git 服务的最佳选择。本实战在华为云 2vCPU/4GiB ECS 上完成了 Gitea v1.26.2 的 Docker 部署、配置、代码推送全流程。84MB 内存消耗、150MB 镜像体积、零外部依赖(仅 SQLite),使其成为小团队私有 Git 托管的首选方案。
核心理念:在 Git-Driven CI/CD 体系中,Gitea 扮演代码源和事件触发器的核心角色——每次
git push都是自动化流水线的起点。
下一步学习
- Gitea + Drone CI:轻量级 CI/CD 全栈方案(无需 Jenkins)
- Gitea Actions:GitHub Actions 兼容的内置 CI/CD
- Gitea + Renovate:自动化依赖更新
- Gitea Package Registry:私有 Docker/NPM/Maven 仓库
- Gitea 高可用部署:MySQL + Redis + 多节点集群
博客完成时间:2026-06-08
实战环境:华为云 ecs-6ce9-0001 · Ubuntu 24.04 · Docker 29.5.3 · Gitea v1.26.2
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)