Gitea 是中小团队自建 Git 服务的最优解——Go 语言开发、资源占用极低(约 50-100MB 内存)、10秒启动、功能完整。本文详解 Gitea 的 rootless 安全部署模式、Docker Compose 配置、初始化流程、SSH 端口配置、用户与仓库管理,以及自动化备份策略,帮助你在有限资源下快速搭建生产可用的代码托管平台。
| 指标 | Gitea | GitLab |
|---|---|---|
| 内存占用 | ~50-100MB | ~2-4GB |
| CPU 需求 | 1核即可 | 建议 2核+ |
| 磁盘空间 | ~1GB | ~10GB+ |
| 启动时间 | ~10秒 | 3-5分钟 |
| 数据库 | SQLite3 内置 | PostgreSQL |
| 适用场景 | 小团队/个人 | 中大型企业 |
参考:在 8GB 内存的服务器上,Gitea 的内存占用通常仅占总内存的 2% 左右(经验值,随仓库规模与并发变化)。
| 维度 | Rootless(推荐) | Root |
|---|---|---|
| 运行用户 | 容器内置普通用户(UID 1000) | root 用户 |
| 安全性 | 高,限制宿主机文件访问 | 低,容器被攻破则宿主机风险大 |
| 最佳实践 | 符合 Docker 安全规范 | 违反最小权限原则 |
| 生产推荐 | 是 | 否 |
Docker 虽然提供了逻辑隔离和网络隔离,但 root 模式下:
Rootless 模式使用容器内普通用户运行进程,即使容器被攻破,权限也有限。
uname -m
# x86_64 → Intel/AMD 64位
# aarch64 → ARM 64位(Apple Silicon、ARM服务器)gitea/gitea:版本号-架构-rootless| 架构 | 镜像标签 |
|---|---|
| x86_64 | gitea/gitea:1.20.1-rootless |
| ARM64 | gitea/gitea:1.20.1-rootless(官方镜像为多架构清单,可直接拉取;Docker Hub 亦提供 1.20.1-linux-arm64-rootless 后缀标签) |
| 最新版 | gitea/gitea:latest-rootless |
官方镜像同时发布于 docker.gitea.com/gitea 与 Docker Hub(gitea/gitea)。务必选择带
rootless后缀的镜像。Docker Hub 搜索技巧:Tags → Filter tags → 输入 "rootless"。
# docker-compose.yml - Gitea rootless 部署
networks:
gitea:
external: false
services:
server:
image: gitea/gitea:1.20.1-rootless
container_name: gitea-server
environment:
- GITEA__database__DB_TYPE=sqlite3
# 如需 MySQL/PostgreSQL:
# - GITEA__database__DB_TYPE=mysql
# - GITEA__database__HOST=db:3306
# - GITEA__database__NAME=gitea
# - GITEA__database__USER=gitea
# - GITEA__database__PASSWD=gitea
restart: always
networks:
- gitea
volumes:
- ./data:/var/lib/gitea
- ./config:/etc/gitea
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "11080:3000" # HTTP 端口
- "11081:22" # SSH 端口| 配置项 | 说明 |
|---|---|
networks: gitea | 内部网络隔离 |
./data → /var/lib/gitea | 数据目录(仓库、数据库) |
./config → /etc/gitea | 配置目录(app.ini) |
timezone/localtime | 时区同步,保证日志时间正确 |
11080:3000 | HTTP 访问端口映射 |
11081:22 | SSH 克隆端口映射 |
GITEA__database__DB_TYPE | 数据库类型,默认 SQLite3 |
# 1. 创建项目目录
mkdir -p ~/gitea && cd ~/gitea
# 2. 创建 docker-compose.yml(粘贴上方配置)
# 3. 创建必要目录
mkdir -p data config
# 4. 设置目录权限(rootless 模式必需!)
# Gitea 容器内使用 UID 1000
sudo chown -R 1000:1000 data config
# 5. 启动服务
docker compose up -d
# 6. 验证运行状态
docker ps | grep gitea
# 7. 查看启动日志
docker logs -f gitea-server
# 看到 "starting new web server" 表示启动成功| 问题 | 原因 | 解决方案 |
|---|---|---|
| 容器反复重启 | data/config 目录不存在或权限不足 | mkdir -p data config && sudo chown -R 1000:1000 data config |
| Permission denied | rootless 模式 UID 不匹配 | 确保目录属主为 UID 1000 |
| 端口被占用 | 端口冲突 | 修改 docker-compose.yml 中的端口映射 |
浏览器访问 http://服务器IP:11080,首次进入自动跳转到安装向导。
| 配置项 | 说明 | 建议 |
|---|---|---|
| 数据库类型 | SQLite3 / MySQL / PostgreSQL | 小团队用 SQLite3 |
| 站点名称 | 显示在页面顶部 | 公司/团队名称 |
| 仓库根路径 | 代码存储位置 | 默认即可 |
| SSH 服务端口 | SSH 克隆使用的端口 | 填 11081(与映射一致) |
| HTTP 端口 | Web 访问端口 | 默认 3000 |
| 基础 URL | 外部访问地址 | 填实际 IP 或域名 |
在初始化页面底部设置管理员账号(用户名、邮箱、密码),点击"立即安装"完成。
~/gitea/config/app.ini[server]
; SSH 对外暴露端口(用户克隆时看到的端口)
SSH_PORT = 11081
; SSH 容器内部监听端口(通常不变)
SSH_LISTEN_PORT = 22
; HTTP 配置
HTTP_PORT = 3000
ROOT_URL = http://192.168.1.100:11080
SSH_PORT是用户在git clone时看到的端口,必须与 docker-compose.yml 中的端口映射一致。
# 编辑配置
vi ~/gitea/config/app.ini
# 修改 SSH_PORT = 11081
# 重启容器生效
docker restart gitea-server# 1. 本地生成密钥
ssh-keygen -t ed25519 -C "your@email.com"
# 2. 查看公钥
cat ~/.ssh/id_ed25519.pub
# 3. 添加到 Gitea
# 浏览器 → 右上角头像 → 设置 → SSH/GPG 密钥 → 添加密钥
# 4. 测试连接
ssh -T git@服务器IP -p 11081
# 5. 克隆仓库
git clone ssh://git@服务器IP:11081/用户名/仓库.git首次连接时系统会记录服务器指纹到 ~/.ssh/known_hosts,后续连接自动验证:
右上角头像 → 管理后台 → 用户账户管理 → 添加用户可执行操作:创建用户、禁用账户、设为管理员、限制用户、删除用户。
创建仓库: 点击 "+" → 创建新仓库 → 设置名称/描述/可见性 → 选择 .gitignore 模板
添加协作者: 仓库 → 设置 → 协作者 → 搜索用户 → 选择权限(读/写)
| 特性 | Gitea | GitLab |
|---|---|---|
| 权限粒度 | 较粗(读/写/管理员) | 精细(多级角色) |
| 权限范围 | 仓库级别 | 项目/组级别 |
| 保护分支 | 支持 | 支持更完善 |
| 审批流程 | 基础 PR 审批 | 完善的 MR 审批链 |
| 适用场景 | 小团队 | 大中型团队 |
| 必须备份 | 说明 |
|---|---|
data/ | 仓库数据、数据库文件 |
config/ | 配置文件(app.ini) |
docker-compose.yml | 部署配置 |
#!/bin/bash
# gitea-backup.sh - Gitea 自动备份脚本
BACKUP_DIR="./backup"
GITEA_DIR="$HOME/gitea"
RETENTION_DAYS=7
mkdir -p $BACKUP_DIR
BACKUP_FILE="gitea-backup-$(date +%Y%m%d-%H%M%S).tar.gz"
echo "开始备份 Gitea..."
# 停止容器确保数据一致性
cd $GITEA_DIR
docker compose down
# 创建备份
tar -czf $BACKUP_DIR/$BACKUP_FILE data/ config/ docker-compose.yml
# 重启服务
docker compose up -d
echo "备份完成:$BACKUP_DIR/$BACKUP_FILE"
# 清理旧备份
find $BACKUP_DIR -name "gitea-backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "已清理 $RETENTION_DAYS 天前的旧备份"crontab -e
# 每天凌晨2点执行备份
0 2 * * * /home/user/gitea/gitea-backup.sh >> /home/user/gitea/backup.log 2>&1# 1. 停止服务
cd ~/gitea && docker compose down
# 2. 解压备份
tar -xzf backup/gitea-backup-YYYYMMDD-HHMMSS.tar.gz
# 3. 确认文件恢复
ls -la data/ config/
# 4. 启动服务
docker compose up -d
# 5. 浏览器验证数据完整[server]
HTTP_PORT = 3000
ROOT_URL = http://192.168.1.100:11080
SSH_PORT = 11081
SSH_LISTEN_PORT = 22
DISABLE_SSH = false
[database]
DB_TYPE = sqlite3
PATH = data/gitea/gitea.db
[repository]
ROOT = /var/lib/gitea/data/gitea-repositories
[security]
INSTALL_LOCK = true
[service]
DISABLE_REGISTRATION = false ; 是否禁止注册
REQUIRE_SIGNIN_VIEW = false ; 是否需要登录才能查看
[mailer]
ENABLED = false修改 app.ini 后需执行
docker restart gitea-server生效。
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 容器反复重启 | 目录权限不足 | chown -R 1000:1000 data config |
| SSH 克隆失败 | SSH 端口配置错误 | 修改 app.ini 中的 SSH_PORT |
| Permission denied | rootless 权限问题 | 确保 UID 1000 有目录权限 |
| 无法访问 Web | 端口未开放 | 检查防火墙和端口映射 |
| 502 错误 | 服务未启动完成 | 等待几秒后刷新 |
| 内存占用偏高 | 使用了外部数据库 | 小团队改用 SQLite3 |
-rootless 镜像即可mkdir 后立即 chown -R 1000:1000,再 docker compose upSSH_PORT 必须与 docker-compose 端口映射一致